@ -57,18 +57,18 @@ float save_corr[4096];
uint32_t prach_Tcp [ 5 ] = { 3168 , 21024 , 6240 , 21024 , 448 } ;
uint32_t prach_Tcp [ 5 ] = { 3168 , 21024 , 6240 , 21024 , 448 } ;
// Table 5.7.1-1 T_seq for preamble formats
// Table 5.7.1-1 T_seq for preamble formats
uint32_t prach_Tseq [ 5 ] = { 24576 , 24576 , 2 * 24576 , 2 * 24576 , 4096 } ;
uint32_t prach_Tseq [ 5 ] = { 24576 , 24576 , 2 * 24576 , 2 * 24576 , 4096 } ;
// Table 5.7.2-2 - N_cs values for unrestricted sets
// Table 5.7.2-2 - N_cs values for unrestricted sets
uint32_t prach_Ncs_unrestricted [ 16 ] = { 0 , 13 , 15 , 18 , 22 , 26 , 32 , 38 , 46 , 59 , 76 , 93 , 119 , 167 , 279 , 419 } ;
uint32_t prach_Ncs_unrestricted [ 16 ] = { 0 , 13 , 15 , 18 , 22 , 26 , 32 , 38 , 46 , 59 , 76 , 93 , 119 , 167 , 279 , 419 } ;
# define MAX_N_zc 839
# define MAX_N_zc 839
// Table 5.7.2-2 - N_cs values for restricted sets
// Table 5.7.2-2 - N_cs values for restricted sets
uint32_t prach_Ncs_restricted [ 15 ] = { 15 , 18 , 22 , 26 , 32 , 38 , 46 , 55 , 68 , 82 , 100 , 128 , 158 , 202 , 237 } ;
uint32_t prach_Ncs_restricted [ 15 ] = { 15 , 18 , 22 , 26 , 32 , 38 , 46 , 55 , 68 , 82 , 100 , 128 , 158 , 202 , 237 } ;
// Table 5.7.2-3 - N_cs values for preamble format 4
// Table 5.7.2-3 - N_cs values for preamble format 4
uint32_t prach_Ncs_format4 [ 7 ] = { 2 , 4 , 6 , 8 , 10 , 12 , 15 } ;
uint32_t prach_Ncs_format4 [ 7 ] = { 2 , 4 , 6 , 8 , 10 , 12 , 15 } ;
// Table 5.7.2-4 - Root ZC sequence order
// Table 5.7.2-4 - Root ZC sequence order
uint32_t prach_zc_roots [ 838 ] = {
uint32_t prach_zc_roots [ 838 ] = {
@ -158,7 +158,6 @@ uint32_t prach_zc_roots_format4[138] = {
61 , 78 , 62 , 77 , 63 , 76 , 64 , 75 , 65 , 74 , 66 , 73 ,
61 , 78 , 62 , 77 , 63 , 76 , 64 , 75 , 65 , 74 , 66 , 73 ,
67 , 72 , 68 , 71 , 69 , 70 } ;
67 , 72 , 68 , 71 , 69 , 70 } ;
srslte_prach_sf_config_t prach_sf_config [ 16 ] = {
srslte_prach_sf_config_t prach_sf_config [ 16 ] = {
{ 1 , { 1 , 0 , 0 , 0 , 0 } } ,
{ 1 , { 1 , 0 , 0 , 0 , 0 } } ,
{ 1 , { 4 , 0 , 0 , 0 , 0 } } ,
{ 1 , { 4 , 0 , 0 , 0 , 0 } } ,
@ -178,11 +177,11 @@ srslte_prach_sf_config_t prach_sf_config[16] = {
{ 1 , { 9 , 0 , 0 , 0 , 0 } } } ;
{ 1 , { 9 , 0 , 0 , 0 , 0 } } } ;
uint32_t srslte_prach_get_preamble_format ( uint32_t config_idx ) {
uint32_t srslte_prach_get_preamble_format ( uint32_t config_idx ) {
return config_idx / 16 ;
return config_idx / 16 ;
}
}
srslte_prach_sfn_t srslte_prach_get_sfn ( uint32_t config_idx ) {
srslte_prach_sfn_t srslte_prach_get_sfn ( uint32_t config_idx ) {
if ( ( config_idx % 16 ) < 3 | | ( config_idx % 16 ) = = 15 ) {
if ( ( config_idx % 16 ) < 3 | | ( config_idx % 16 ) = = 15 ) {
return SRSLTE_PRACH_SFN_EVEN ;
return SRSLTE_PRACH_SFN_EVEN ;
} else {
} else {
return SRSLTE_PRACH_SFN_ANY ;
return SRSLTE_PRACH_SFN_ANY ;
@ -192,26 +191,23 @@ srslte_prach_sfn_t srslte_prach_get_sfn(uint32_t config_idx) {
/* Returns true if current_tti is a valid opportunity for PRACH transmission and the is an allowed subframe,
/* Returns true if current_tti is a valid opportunity for PRACH transmission and the is an allowed subframe,
* or allowed_subframe = = - 1
* or allowed_subframe = = - 1
*/
*/
bool srslte_prach_tti_opportunity ( srslte_prach_t * p , uint32_t current_tti , int allowed_subframe )
bool srslte_prach_tti_opportunity ( srslte_prach_t * p , uint32_t current_tti , int allowed_subframe ) {
{
uint32_t config_idx = p - > config_idx ;
uint32_t config_idx = p - > config_idx ;
// Get SFN and sf_idx from the PRACH configuration index
// Get SFN and sf_idx from the PRACH configuration index
srslte_prach_sfn_t prach_sfn = srslte_prach_get_sfn ( config_idx ) ;
srslte_prach_sfn_t prach_sfn = srslte_prach_get_sfn ( config_idx ) ;
// This is the only option which provides always an opportunity for PRACH transmission.
// This is the only option which provides always an opportunity for PRACH transmission.
if ( config_idx = = 14 ) {
if ( config_idx = = 14 ) {
return true ;
return true ;
}
}
if ( ( prach_sfn = = SRSLTE_PRACH_SFN_EVEN & & ( ( current_tti / 10 ) % 2 ) = = 0 ) | |
if ( ( prach_sfn = = SRSLTE_PRACH_SFN_EVEN & & ( ( current_tti / 10 ) % 2 ) = = 0 ) | |
prach_sfn = = SRSLTE_PRACH_SFN_ANY )
prach_sfn = = SRSLTE_PRACH_SFN_ANY ) {
{
srslte_prach_sf_config_t sf_config ;
srslte_prach_sf_config_t sf_config ;
srslte_prach_sf_config ( config_idx , & sf_config ) ;
srslte_prach_sf_config ( config_idx , & sf_config ) ;
for ( int i = 0 ; i < sf_config . nof_sf ; i + + ) {
for ( int i = 0 ; i < sf_config . nof_sf ; i + + ) {
if ( ( ( current_tti % 10 ) = = sf_config . sf [ i ] & & allowed_subframe = = - 1 ) | |
if ( ( ( current_tti % 10 ) = = sf_config . sf [ i ] & & allowed_subframe = = - 1 ) | |
( ( current_tti % 10 ) = = sf_config . sf [ i ] & & ( current_tti % 10 ) = = allowed_subframe ) )
( ( current_tti % 10 ) = = sf_config . sf [ i ] & & ( current_tti % 10 ) = = allowed_subframe ) ) {
{
return true ;
return true ;
}
}
}
}
@ -219,23 +215,19 @@ bool srslte_prach_tti_opportunity(srslte_prach_t *p, uint32_t current_tti, int a
return false ;
return false ;
}
}
void srslte_prach_sf_config ( uint32_t config_idx , srslte_prach_sf_config_t * sf_config ) {
void srslte_prach_sf_config ( uint32_t config_idx , srslte_prach_sf_config_t * sf_config ) {
memcpy ( sf_config , & prach_sf_config [ config_idx % 16 ] , sizeof ( srslte_prach_sf_config_t ) ) ;
memcpy ( sf_config , & prach_sf_config [ config_idx % 16 ] , sizeof ( srslte_prach_sf_config_t ) ) ;
}
}
// For debug use only
// For debug use only
void print ( void * d , uint32_t size , uint32_t len , char * file_str )
void print ( void * d , uint32_t size , uint32_t len , char * file_str ) {
{
FILE * f ;
FILE * f ;
f = fopen ( file_str , " wb " ) ;
f = fopen ( file_str , " wb " ) ;
fwrite ( d , size , len , f ) ;
fwrite ( d , size , len , f ) ;
fclose ( f ) ;
fclose ( f ) ;
}
}
int srslte_prach_gen_seqs ( srslte_prach_t * p )
int srslte_prach_gen_seqs ( srslte_prach_t * p ) {
{
uint32_t u = 0 ;
uint32_t u = 0 ;
uint32_t v = 1 ;
uint32_t v = 1 ;
int v_max = 0 ;
int v_max = 0 ;
@ -249,79 +241,85 @@ int srslte_prach_gen_seqs(srslte_prach_t *p)
cf_t root [ 839 ] ;
cf_t root [ 839 ] ;
// Generate our 64 preamble sequences
// Generate our 64 preamble sequences
for ( int i = 0 ; i < N_SEQS ; i + + ) {
for ( int i = 0 ; i < N_SEQS ; i + + ) {
if ( v > v_max ) {
if ( v > v_max ) {
// Get a new root sequence
// Get a new root sequence
if ( 4 = = p - > f ) {
if ( 4 = = p - > f ) {
u = prach_zc_roots_format4 [ ( p - > rsi + p - > N_roots ) % 138 ] ;
u = prach_zc_roots_format4 [ ( p - > rsi + p - > N_roots ) % 138 ] ;
} else {
} else {
u = prach_zc_roots [ ( p - > rsi + p - > N_roots ) % 838 ] ;
u = prach_zc_roots [ ( p - > rsi + p - > N_roots ) % 838 ] ;
}
}
for ( int j = 0 ; j < p - > N_zc ; j + + ) {
for ( int j = 0 ; j < p - > N_zc ; j + + ) {
double phase = - M_PI * u * j * ( j + 1 ) / p - > N_zc ;
double phase = - M_PI * u * j * ( j + 1 ) / p - > N_zc ;
root [ j ] = cexp ( phase * I ) ;
root [ j ] = cexp ( phase * I ) ;
}
}
p - > root_seqs_idx [ p - > N_roots + + ] = i ;
p - > root_seqs_idx [ p - > N_roots + + ] = i ;
// Determine v_max
// Determine v_max
if ( p - > hs ) {
if ( p - > hs ) {
// High-speed cell
// High-speed cell
for ( p_ = 1 ; p_ < = p - > N_zc ; p_ + + ) {
for ( p_ = 1 ; p_ < = p - > N_zc ; p_ + + ) {
if ( ( ( p_ * u ) % p - > N_zc ) = = 1 )
if ( ( ( p_ * u ) % p - > N_zc ) = = 1 )
break ;
break ;
}
}
if ( p_ < p - > N_zc / 2 ) {
if ( p_ < p - > N_zc / 2 ) {
d_u = p_ ;
d_u = p_ ;
} else {
} else {
d_u = p - > N_zc - p_ ;
d_u = p - > N_zc - p_ ;
}
}
if ( d_u > = p - > N_cs & & d_u < p - > N_zc / 3 ) {
if ( d_u > = p - > N_cs & & d_u < p - > N_zc / 3 ) {
N_shift = d_u / p - > N_cs ;
N_shift = d_u / p - > N_cs ;
d_start = 2 * d_u + N_shift * p - > N_cs ;
d_start = 2 * d_u + N_shift * p - > N_cs ;
N_group = p - > N_zc / d_start ;
N_group = p - > N_zc / d_start ;
N_neg_shift = ( p - > N_zc - 2 * d_u - N_group * d_start ) / p - > N_cs ;
if ( p - > N_zc > 2 * d_u + N_group * d_start ) {
if ( N_neg_shift < 0 )
N_neg_shift = ( p - > N_zc - 2 * d_u - N_group * d_start ) / p - > N_cs ;
} else {
N_neg_shift = 0 ;
N_neg_shift = 0 ;
} else {
}
N_shift = ( p - > N_zc - 2 * d_u ) / p - > N_cs ;
} else if ( p - > N_zc / 3 < = d_u & & d_u < = ( p - > N_zc - p - > N_cs ) / 2 ) {
d_start = p - > N_zc - 2 * d_u + N_shift * p - > N_cs ;
N_shift = ( p - > N_zc - 2 * d_u ) / p - > N_cs ;
N_group = d_u / d_start ;
d_start = p - > N_zc - 2 * d_u + N_shift * p - > N_cs ;
N_neg_shift = ( d_u - N_group * d_start ) / p - > N_cs ;
N_group = d_u / d_start ;
if ( N_neg_shift < 0 )
if ( d_u > N_group * d_start ) {
N_neg_shift = ( d_u - N_group * d_start ) / p - > N_cs ;
} else {
N_neg_shift = 0 ;
N_neg_shift = 0 ;
if ( N_neg_shift > N_shift )
}
if ( N_neg_shift > N_shift )
N_neg_shift = N_shift ;
N_neg_shift = N_shift ;
} else {
N_shift = 0 ;
}
}
v_max = N_shift * N_group + N_neg_shift - 1 ;
v_max = N_shift * N_group + N_neg_shift - 1 ;
if ( v_max < 0 ) {
if ( v_max < 0 ) {
v_max = 0 ;
v_max = 0 ;
}
}
} else {
} else {
// Normal cell
// Normal cell
if ( 0 = = p - > N_cs ) {
if ( 0 = = p - > N_cs ) {
v_max = 0 ;
v_max = 0 ;
} else {
} else {
v_max = ( p - > N_zc / p - > N_cs ) - 1 ;
v_max = ( p - > N_zc / p - > N_cs ) - 1 ;
}
}
}
}
v = 0 ;
v = 0 ;
}
}
// Shift root and add to set
// Shift root and add to set
if ( p - > hs ) {
if ( p - > hs ) {
if ( N_shift = = 0 ) {
if ( N_shift = = 0 ) {
C_v = 0 ;
C_v = 0 ;
} else {
} else {
C_v = d_start * floor ( v / N_shift ) + ( v % N_shift ) * p - > N_cs ;
C_v = d_start * floor ( v / N_shift ) + ( v % N_shift ) * p - > N_cs ;
}
}
} else {
} else {
C_v = v * p - > N_cs ;
C_v = v * p - > N_cs ;
}
}
for ( int j = 0 ; j < p - > N_zc ; j + + ) {
for ( int j = 0 ; j < p - > N_zc ; j + + ) {
p - > seqs [ i ] [ j ] = root [ ( j + C_v ) % p - > N_zc ] ;
p - > seqs [ i ] [ j ] = root [ ( j + C_v ) % p - > N_zc ] ;
}
}
v + + ;
v + + ;
@ -329,8 +327,7 @@ int srslte_prach_gen_seqs(srslte_prach_t *p)
return 0 ;
return 0 ;
}
}
int srslte_prach_init_cfg ( srslte_prach_t * p , srslte_prach_cfg_t * cfg , uint32_t nof_prb )
int srslte_prach_init_cfg ( srslte_prach_t * p , srslte_prach_cfg_t * cfg , uint32_t nof_prb ) {
{
if ( srslte_prach_init ( p , srslte_symbol_sz ( nof_prb ) ) ) {
if ( srslte_prach_init ( p , srslte_symbol_sz ( nof_prb ) ) ) {
return - 1 ;
return - 1 ;
}
}
@ -342,51 +339,49 @@ int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t n
cfg - > zero_corr_zone ) ;
cfg - > zero_corr_zone ) ;
}
}
int srslte_prach_init ( srslte_prach_t * p , uint32_t max_N_ifft_ul )
int srslte_prach_init ( srslte_prach_t * p , uint32_t max_N_ifft_ul ) {
{
int ret = SRSLTE_ERROR ;
int ret = SRSLTE_ERROR ;
if ( p ! = NULL & &
if ( p ! = NULL & &
max_N_ifft_ul < 2049 )
max_N_ifft_ul < 2049 ) {
{
bzero ( p , sizeof ( srslte_prach_t ) ) ;
bzero ( p , sizeof ( srslte_prach_t ) ) ;
p - > max_N_ifft_ul = max_N_ifft_ul ;
p - > max_N_ifft_ul = max_N_ifft_ul ;
// Set up containers
// Set up containers
p - > prach_bins = srslte_vec_malloc ( sizeof ( cf_t ) * MAX_N_zc ) ;
p - > prach_bins = srslte_vec_malloc ( sizeof ( cf_t ) * MAX_N_zc ) ;
p - > corr_spec = srslte_vec_malloc ( sizeof ( cf_t ) * MAX_N_zc ) ;
p - > corr_spec = srslte_vec_malloc ( sizeof ( cf_t ) * MAX_N_zc ) ;
p - > corr = srslte_vec_malloc ( sizeof ( float ) * MAX_N_zc ) ;
p - > corr = srslte_vec_malloc ( sizeof ( float ) * MAX_N_zc ) ;
// Set up ZC FFTS
// Set up ZC FFTS
if ( srslte_dft_plan ( & p - > zc_fft , MAX_N_zc , SRSLTE_DFT_FORWARD , SRSLTE_DFT_COMPLEX ) ) {
if ( srslte_dft_plan ( & p - > zc_fft , MAX_N_zc , SRSLTE_DFT_FORWARD , SRSLTE_DFT_COMPLEX ) ) {
return SRSLTE_ERROR ;
return SRSLTE_ERROR ;
}
}
srslte_dft_plan_set_mirror ( & p - > zc_fft , false ) ;
srslte_dft_plan_set_mirror ( & p - > zc_fft , false ) ;
srslte_dft_plan_set_norm ( & p - > zc_fft , true ) ;
srslte_dft_plan_set_norm ( & p - > zc_fft , true ) ;
if ( srslte_dft_plan ( & p - > zc_ifft , MAX_N_zc , SRSLTE_DFT_BACKWARD , SRSLTE_DFT_COMPLEX ) ) {
if ( srslte_dft_plan ( & p - > zc_ifft , MAX_N_zc , SRSLTE_DFT_BACKWARD , SRSLTE_DFT_COMPLEX ) ) {
return SRSLTE_ERROR ;
return SRSLTE_ERROR ;
}
}
srslte_dft_plan_set_mirror ( & p - > zc_ifft , false ) ;
srslte_dft_plan_set_mirror ( & p - > zc_ifft , false ) ;
srslte_dft_plan_set_norm ( & p - > zc_ifft , false ) ;
srslte_dft_plan_set_norm ( & p - > zc_ifft , false ) ;
uint32_t fft_size_alloc = max_N_ifft_ul * DELTA_F / DELTA_F_RA ;
uint32_t fft_size_alloc = max_N_ifft_ul * DELTA_F / DELTA_F_RA ;
p - > ifft_in = ( cf_t * ) srslte_vec_malloc ( fft_size_alloc * sizeof ( cf_t ) ) ;
p - > ifft_in = ( cf_t * ) srslte_vec_malloc ( fft_size_alloc * sizeof ( cf_t ) ) ;
p - > ifft_out = ( cf_t * ) srslte_vec_malloc ( fft_size_alloc * sizeof ( cf_t ) ) ;
p - > ifft_out = ( cf_t * ) srslte_vec_malloc ( fft_size_alloc * sizeof ( cf_t ) ) ;
if ( srslte_dft_plan ( & p - > ifft , fft_size_alloc , SRSLTE_DFT_BACKWARD , SRSLTE_DFT_COMPLEX ) ) {
if ( srslte_dft_plan ( & p - > ifft , fft_size_alloc , SRSLTE_DFT_BACKWARD , SRSLTE_DFT_COMPLEX ) ) {
fprintf ( stderr , " Error creating DFT plan \n " ) ;
fprintf ( stderr , " Error creating DFT plan \n " ) ;
return - 1 ;
return - 1 ;
}
}
srslte_dft_plan_set_mirror ( & p - > ifft , true ) ;
srslte_dft_plan_set_mirror ( & p - > ifft , true ) ;
srslte_dft_plan_set_norm ( & p - > ifft , true ) ;
srslte_dft_plan_set_norm ( & p - > ifft , true ) ;
if ( srslte_dft_plan ( & p - > fft , fft_size_alloc , SRSLTE_DFT_FORWARD , SRSLTE_DFT_COMPLEX ) ) {
if ( srslte_dft_plan ( & p - > fft , fft_size_alloc , SRSLTE_DFT_FORWARD , SRSLTE_DFT_COMPLEX ) ) {
fprintf ( stderr , " Error creating DFT plan \n " ) ;
fprintf ( stderr , " Error creating DFT plan \n " ) ;
return - 1 ;
return - 1 ;
}
}
p - > signal_fft = srslte_vec_malloc ( sizeof ( cf_t ) * fft_size_alloc ) ;
p - > signal_fft = srslte_vec_malloc ( sizeof ( cf_t ) * fft_size_alloc ) ;
if ( ! p - > signal_fft ) {
if ( ! p - > signal_fft ) {
fprintf ( stderr , " Error allocating memory \n " ) ;
fprintf ( stderr , " Error allocating memory \n " ) ;
return - 1 ;
return - 1 ;
@ -403,20 +398,17 @@ int srslte_prach_init(srslte_prach_t *p, uint32_t max_N_ifft_ul)
return ret ;
return ret ;
}
}
int srslte_prach_set_cell ( srslte_prach_t * p ,
int srslte_prach_set_cell ( srslte_prach_t * p ,
uint32_t N_ifft_ul ,
uint32_t N_ifft_ul ,
uint32_t config_idx ,
uint32_t config_idx ,
uint32_t root_seq_index ,
uint32_t root_seq_index ,
bool high_speed_flag ,
bool high_speed_flag ,
uint32_t zero_corr_zone_config )
uint32_t zero_corr_zone_config ) {
{
int ret = SRSLTE_ERROR ;
int ret = SRSLTE_ERROR ;
if ( p ! = NULL & &
if ( p ! = NULL & &
N_ifft_ul < 2049 & &
N_ifft_ul < 2049 & &
config_idx < 64 & &
config_idx < 64 & &
root_seq_index < MAX_ROOTS )
root_seq_index < MAX_ROOTS ) {
{
if ( N_ifft_ul > p - > max_N_ifft_ul ) {
if ( N_ifft_ul > p - > max_N_ifft_ul ) {
fprintf ( stderr , " PRACH: Error in set_cell(): N_ifft_ul must be lower or equal max_N_ifft_ul in init() \n " ) ;
fprintf ( stderr , " PRACH: Error in set_cell(): N_ifft_ul must be lower or equal max_N_ifft_ul in init() \n " ) ;
return - 1 ;
return - 1 ;
@ -432,7 +424,7 @@ int srslte_prach_set_cell(srslte_prach_t *p,
// Determine N_zc and N_cs
// Determine N_zc and N_cs
if ( 4 = = preamble_format ) {
if ( 4 = = preamble_format ) {
if ( p - > zczc < 7 ) {
if ( p - > zczc < 7 ) {
p - > N_zc = 139 ;
p - > N_zc = 139 ;
p - > N_cs = prach_Ncs_format4 [ p - > zczc ] ;
p - > N_cs = prach_Ncs_format4 [ p - > zczc ] ;
@ -440,16 +432,16 @@ int srslte_prach_set_cell(srslte_prach_t *p,
fprintf ( stderr , " Invalid zeroCorrelationZoneConfig=%d for format4 \n " , p - > zczc ) ;
fprintf ( stderr , " Invalid zeroCorrelationZoneConfig=%d for format4 \n " , p - > zczc ) ;
return SRSLTE_ERROR ;
return SRSLTE_ERROR ;
}
}
} else {
} else {
p - > N_zc = MAX_N_zc ;
p - > N_zc = MAX_N_zc ;
if ( p - > hs ) {
if ( p - > hs ) {
if ( p - > zczc < 15 ) {
if ( p - > zczc < 15 ) {
p - > N_cs = prach_Ncs_restricted [ p - > zczc ] ;
p - > N_cs = prach_Ncs_restricted [ p - > zczc ] ;
} else {
} else {
fprintf ( stderr , " Invalid zeroCorrelationZoneConfig=%d for restricted set \n " , p - > zczc ) ;
fprintf ( stderr , " Invalid zeroCorrelationZoneConfig=%d for restricted set \n " , p - > zczc ) ;
return SRSLTE_ERROR ;
return SRSLTE_ERROR ;
}
}
} else {
} else {
if ( p - > zczc < 16 ) {
if ( p - > zczc < 16 ) {
p - > N_cs = prach_Ncs_unrestricted [ p - > zczc ] ;
p - > N_cs = prach_Ncs_unrestricted [ p - > zczc ] ;
} else {
} else {
@ -461,10 +453,10 @@ int srslte_prach_set_cell(srslte_prach_t *p,
// Set up ZC FFTS
// Set up ZC FFTS
if ( p - > N_zc ! = MAX_N_zc ) {
if ( p - > N_zc ! = MAX_N_zc ) {
if ( srslte_dft_replan ( & p - > zc_fft , p - > N_zc ) ) {
if ( srslte_dft_replan ( & p - > zc_fft , p - > N_zc ) ) {
return SRSLTE_ERROR ;
return SRSLTE_ERROR ;
}
}
if ( srslte_dft_replan ( & p - > zc_ifft , p - > N_zc ) ) {
if ( srslte_dft_replan ( & p - > zc_ifft , p - > N_zc ) ) {
return SRSLTE_ERROR ;
return SRSLTE_ERROR ;
}
}
}
}
@ -474,16 +466,16 @@ int srslte_prach_set_cell(srslte_prach_t *p,
srslte_prach_gen_seqs ( p ) ;
srslte_prach_gen_seqs ( p ) ;
// Generate sequence FFTs
// Generate sequence FFTs
for ( int i = 0 ; i < N_SEQS ; i + + ) {
for ( int i = 0 ; i < N_SEQS ; i + + ) {
srslte_dft_run ( & p - > zc_fft , p - > seqs [ i ] , p - > dft_seqs [ i ] ) ;
srslte_dft_run ( & p - > zc_fft , p - > seqs [ i ] , p - > dft_seqs [ i ] ) ;
}
}
// Create our FFT objects and buffers
// Create our FFT objects and buffers
p - > N_ifft_ul = N_ifft_ul ;
p - > N_ifft_ul = N_ifft_ul ;
if ( 4 = = preamble_format ) {
if ( 4 = = preamble_format ) {
p - > N_ifft_prach = p - > N_ifft_ul * DELTA_F / DELTA_F_RA_4 ;
p - > N_ifft_prach = p - > N_ifft_ul * DELTA_F / DELTA_F_RA_4 ;
} else {
} else {
p - > N_ifft_prach = p - > N_ifft_ul * DELTA_F / DELTA_F_RA ;
p - > N_ifft_prach = p - > N_ifft_ul * DELTA_F / DELTA_F_RA ;
}
}
/* The deadzone specifies the number of samples at the end of the correlation window
/* The deadzone specifies the number of samples at the end of the correlation window
@ -496,19 +488,19 @@ int srslte_prach_set_cell(srslte_prach_t *p,
p - > deadzone = ( uint32_t ) ceil ( ( float ) samp_rate / ( ( float ) p - > N_zc * subcarrier_spacing ) ) ;
p - > deadzone = ( uint32_t ) ceil ( ( float ) samp_rate / ( ( float ) p - > N_zc * subcarrier_spacing ) ) ;
} */
} */
if ( srslte_dft_replan ( & p - > ifft , p - > N_ifft_prach ) ) {
if ( srslte_dft_replan ( & p - > ifft , p - > N_ifft_prach ) ) {
fprintf ( stderr , " Error creating DFT plan \n " ) ;
fprintf ( stderr , " Error creating DFT plan \n " ) ;
return - 1 ;
return - 1 ;
}
}
if ( srslte_dft_replan ( & p - > fft , p - > N_ifft_prach ) ) {
if ( srslte_dft_replan ( & p - > fft , p - > N_ifft_prach ) ) {
fprintf ( stderr , " Error creating DFT plan \n " ) ;
fprintf ( stderr , " Error creating DFT plan \n " ) ;
return - 1 ;
return - 1 ;
}
}
p - > N_seq = prach_Tseq [ p - > f ] * p - > N_ifft_ul / 2048 ;
p - > N_seq = prach_Tseq [ p - > f ] * p - > N_ifft_ul / 2048 ;
p - > N_cp = prach_Tcp [ p - > f ] * p - > N_ifft_ul / 2048 ;
p - > N_cp = prach_Tcp [ p - > f ] * p - > N_ifft_ul / 2048 ;
p - > T_seq = prach_Tseq [ p - > f ] * SRSLTE_LTE_TS ;
p - > T_seq = prach_Tseq [ p - > f ] * SRSLTE_LTE_TS ;
p - > T_tot = ( prach_Tseq [ p - > f ] + prach_Tcp [ p - > f ] ) * SRSLTE_LTE_TS ;
p - > T_tot = ( prach_Tseq [ p - > f ] + prach_Tcp [ p - > f ] ) * SRSLTE_LTE_TS ;
ret = SRSLTE_SUCCESS ;
ret = SRSLTE_SUCCESS ;
} else {
} else {
@ -521,18 +513,16 @@ int srslte_prach_set_cell(srslte_prach_t *p,
int srslte_prach_gen ( srslte_prach_t * p ,
int srslte_prach_gen ( srslte_prach_t * p ,
uint32_t seq_index ,
uint32_t seq_index ,
uint32_t freq_offset ,
uint32_t freq_offset ,
cf_t * signal )
cf_t * signal ) {
{
int ret = SRSLTE_ERROR ;
int ret = SRSLTE_ERROR ;
if ( p ! = NULL & &
if ( p ! = NULL & &
seq_index < N_SEQS & &
seq_index < N_SEQS & &
signal ! = NULL )
signal ! = NULL ) {
{
// Calculate parameters
// Calculate parameters
uint32_t N_rb_ul = srslte_nof_prb ( p - > N_ifft_ul ) ;
uint32_t N_rb_ul = srslte_nof_prb ( p - > N_ifft_ul ) ;
uint32_t k_0 = freq_offset * N_RB_SC - N_rb_ul * N_RB_SC / 2 + p - > N_ifft_ul / 2 ;
uint32_t k_0 = freq_offset * N_RB_SC - N_rb_ul * N_RB_SC / 2 + p - > N_ifft_ul / 2 ;
uint32_t K = DELTA_F / DELTA_F_RA ;
uint32_t K = DELTA_F / DELTA_F_RA ;
uint32_t begin = PHI + ( K * k_0 ) + ( K / 2 ) ;
uint32_t begin = PHI + ( K * k_0 ) + ( K / 2 ) ;
if ( 6 + freq_offset > N_rb_ul ) {
if ( 6 + freq_offset > N_rb_ul ) {
fprintf ( stderr , " Error no space for PRACH: frequency offset=%d, N_rb_ul=%d \n " , freq_offset , N_rb_ul ) ;
fprintf ( stderr , " Error no space for PRACH: frequency offset=%d, N_rb_ul=%d \n " , freq_offset , N_rb_ul ) ;
@ -543,18 +533,18 @@ int srslte_prach_gen(srslte_prach_t *p,
p - > N_zc , p - > N_cp , p - > N_seq , p - > N_ifft_prach , begin ) ;
p - > N_zc , p - > N_cp , p - > N_seq , p - > N_ifft_prach , begin ) ;
// Map dft-precoded sequence to ifft bins
// Map dft-precoded sequence to ifft bins
memset ( p - > ifft_in , 0 , begin * sizeof ( cf_t ) ) ;
memset ( p - > ifft_in , 0 , begin * sizeof ( cf_t ) ) ;
memcpy ( & p - > ifft_in [ begin ] , p - > dft_seqs [ seq_index ] , p - > N_zc * sizeof ( cf_t ) ) ;
memcpy ( & p - > ifft_in [ begin ] , p - > dft_seqs [ seq_index ] , p - > N_zc * sizeof ( cf_t ) ) ;
memset ( & p - > ifft_in [ begin + p - > N_zc ] , 0 , ( p - > N_ifft_prach - begin - p - > N_zc ) * sizeof ( cf_t ) ) ;
memset ( & p - > ifft_in [ begin + p - > N_zc ] , 0 , ( p - > N_ifft_prach - begin - p - > N_zc ) * sizeof ( cf_t ) ) ;
srslte_dft_run ( & p - > ifft , p - > ifft_in , p - > ifft_out ) ;
srslte_dft_run ( & p - > ifft , p - > ifft_in , p - > ifft_out ) ;
// Copy CP into buffer
// Copy CP into buffer
memcpy ( signal , & p - > ifft_out [ p - > N_ifft_prach - p - > N_cp ] , p - > N_cp * sizeof ( cf_t ) ) ;
memcpy ( signal , & p - > ifft_out [ p - > N_ifft_prach - p - > N_cp ] , p - > N_cp * sizeof ( cf_t ) ) ;
// Copy preamble sequence into buffer
// Copy preamble sequence into buffer
for ( int i = 0 ; i < p - > N_seq ; i + + ) {
for ( int i = 0 ; i < p - > N_seq ; i + + ) {
signal [ p - > N_cp + i ] = p - > ifft_out [ i % p - > N_ifft_prach ] ;
signal [ p - > N_cp + i ] = p - > ifft_out [ i % p - > N_ifft_prach ] ;
}
}
ret = SRSLTE_SUCCESS ;
ret = SRSLTE_SUCCESS ;
@ -572,8 +562,7 @@ int srslte_prach_detect(srslte_prach_t *p,
cf_t * signal ,
cf_t * signal ,
uint32_t sig_len ,
uint32_t sig_len ,
uint32_t * indices ,
uint32_t * indices ,
uint32_t * n_indices )
uint32_t * n_indices ) {
{
return srslte_prach_detect_offset ( p , freq_offset , signal , sig_len , indices , NULL , NULL , n_indices ) ;
return srslte_prach_detect_offset ( p , freq_offset , signal , sig_len , indices , NULL , NULL , n_indices ) ;
}
}
@ -584,16 +573,14 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
uint32_t * indices ,
uint32_t * indices ,
float * t_offsets ,
float * t_offsets ,
float * peak_to_avg ,
float * peak_to_avg ,
uint32_t * n_indices )
uint32_t * n_indices ) {
{
int ret = SRSLTE_ERROR ;
int ret = SRSLTE_ERROR ;
if ( p ! = NULL & &
if ( p ! = NULL & &
signal ! = NULL & &
signal ! = NULL & &
sig_len > 0 & &
sig_len > 0 & &
indices ! = NULL )
indices ! = NULL ) {
{
if ( sig_len < p - > N_ifft_prach ) {
if ( sig_len < p - > N_ifft_prach ) {
fprintf ( stderr , " srslte_prach_detect: Signal length is %d and should be %d \n " , sig_len , p - > N_ifft_prach ) ;
fprintf ( stderr , " srslte_prach_detect: Signal length is %d and should be %d \n " , sig_len , p - > N_ifft_prach ) ;
return SRSLTE_ERROR_INVALID_INPUTS ;
return SRSLTE_ERROR_INVALID_INPUTS ;
}
}
@ -605,13 +592,13 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
// Extract bins of interest
// Extract bins of interest
uint32_t N_rb_ul = srslte_nof_prb ( p - > N_ifft_ul ) ;
uint32_t N_rb_ul = srslte_nof_prb ( p - > N_ifft_ul ) ;
uint32_t k_0 = freq_offset * N_RB_SC - N_rb_ul * N_RB_SC / 2 + p - > N_ifft_ul / 2 ;
uint32_t k_0 = freq_offset * N_RB_SC - N_rb_ul * N_RB_SC / 2 + p - > N_ifft_ul / 2 ;
uint32_t K = DELTA_F / DELTA_F_RA ;
uint32_t K = DELTA_F / DELTA_F_RA ;
uint32_t begin = PHI + ( K * k_0 ) + ( K / 2 ) ;
uint32_t begin = PHI + ( K * k_0 ) + ( K / 2 ) ;
memcpy ( p - > prach_bins , & p - > signal_fft [ begin ] , p - > N_zc * sizeof ( cf_t ) ) ;
memcpy ( p - > prach_bins , & p - > signal_fft [ begin ] , p - > N_zc * sizeof ( cf_t ) ) ;
for ( int i = 0 ; i < p - > N_roots ; i + + ) {
for ( int i = 0 ; i < p - > N_roots ; i + + ) {
cf_t * root_spec = p - > dft_seqs [ p - > root_seqs_idx [ i ] ] ;
cf_t * root_spec = p - > dft_seqs [ p - > root_seqs_idx [ i ] ] ;
srslte_vec_prod_conj_ccc ( p - > prach_bins , root_spec , p - > corr_spec , p - > N_zc ) ;
srslte_vec_prod_conj_ccc ( p - > prach_bins , root_spec , p - > corr_spec , p - > N_zc ) ;
@ -620,49 +607,48 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
srslte_vec_abs_square_cf ( p - > corr_spec , p - > corr , p - > N_zc ) ;
srslte_vec_abs_square_cf ( p - > corr_spec , p - > corr , p - > N_zc ) ;
float corr_ave = srslte_vec_acc_ff ( p - > corr , p - > N_zc ) / p - > N_zc ;
float corr_ave = srslte_vec_acc_ff ( p - > corr , p - > N_zc ) / p - > N_zc ;
uint32_t winsize = 0 ;
uint32_t winsize = 0 ;
if ( p - > N_cs ! = 0 ) {
if ( p - > N_cs ! = 0 ) {
winsize = p - > N_cs ;
winsize = p - > N_cs ;
} else {
} else {
winsize = p - > N_zc ;
winsize = p - > N_zc ;
}
}
uint32_t n_wins = p - > N_zc / winsize ;
uint32_t n_wins = p - > N_zc / winsize ;
float max_peak = 0 ;
float max_peak = 0 ;
for ( int j = 0 ; j < n_wins ; j + + ) {
for ( int j = 0 ; j < n_wins ; j + + ) {
uint32_t start = ( p - > N_zc - ( j * p - > N_cs ) ) % p - > N_zc ;
uint32_t start = ( p - > N_zc - ( j * p - > N_cs ) ) % p - > N_zc ;
uint32_t end = start + winsize ;
uint32_t end = start + winsize ;
if ( end > p - > deadzone ) {
if ( end > p - > deadzone ) {
end - = p - > deadzone ;
end - = p - > deadzone ;
}
}
start + = p - > deadzone ;
start + = p - > deadzone ;
p - > peak_values [ j ] = 0 ;
p - > peak_values [ j ] = 0 ;
for ( int k = start ; k < end ; k + + ) {
for ( int k = start ; k < end ; k + + ) {
if ( p - > corr [ k ] > p - > peak_values [ j ] ) {
if ( p - > corr [ k ] > p - > peak_values [ j ] ) {
p - > peak_values [ j ] = p - > corr [ k ] ;
p - > peak_values [ j ] = p - > corr [ k ] ;
p - > peak_offsets [ j ] = k - start ;
p - > peak_offsets [ j ] = k - start ;
if ( p - > peak_values [ j ] > max_peak ) {
if ( p - > peak_values [ j ] > max_peak ) {
max_peak = p - > peak_values [ j ] ;
max_peak = p - > peak_values [ j ] ;
}
}
}
}
}
}
}
}
if ( max_peak > p - > detect_factor * corr_ave ) {
if ( max_peak > p - > detect_factor * corr_ave ) {
for ( int j = 0 ; j < n_wins ; j + + ) {
for ( int j = 0 ; j < n_wins ; j + + ) {
if ( p - > peak_values [ j ] > p - > detect_factor * corr_ave )
if ( p - > peak_values [ j ] > p - > detect_factor * corr_ave ) {
{
//printf("saving prach correlation\n");
//printf("saving prach correlation\n");
//memcpy(save_corr, p->corr, p->N_zc*sizeof(float));
//memcpy(save_corr, p->corr, p->N_zc*sizeof(float));
if ( indices ) {
if ( indices ) {
indices [ * n_indices ] = ( i * n_wins ) + j ;
indices [ * n_indices ] = ( i * n_wins ) + j ;
}
}
if ( peak_to_avg ) {
if ( peak_to_avg ) {
peak_to_avg [ * n_indices ] = p - > peak_values [ j ] / corr_ave ;
peak_to_avg [ * n_indices ] = p - > peak_values [ j ] / corr_ave ;
}
}
if ( t_offsets ) {
if ( t_offsets ) {
t_offsets [ * n_indices ] = ( float ) p - > peak_offsets [ j ] * p - > T_seq / p - > N_zc ;
t_offsets [ * n_indices ] = ( float ) p - > peak_offsets [ j ] * p - > T_seq / p - > N_zc ;
}
}
( * n_indices ) + + ;
( * n_indices ) + + ;
}
}
@ -695,33 +681,29 @@ int srslte_prach_free(srslte_prach_t *p) {
return 0 ;
return 0 ;
}
}
int srslte_prach_print_seqs ( srslte_prach_t * p )
int srslte_prach_print_seqs ( srslte_prach_t * p ) {
{
for ( int i = 0 ; i < N_SEQS ; i + + ) {
for ( int i = 0 ; i < N_SEQS ; i + + )
{
FILE * f ;
FILE * f ;
char str [ 32 ] ;
char str [ 32 ] ;
sprintf ( str , " prach_seq_%d.bin " , i ) ;
sprintf ( str , " prach_seq_%d.bin " , i ) ;
f = fopen ( str , " wb " ) ;
f = fopen ( str , " wb " ) ;
fwrite ( p - > seqs [ i ] , sizeof ( cf_t ) , p - > N_zc , f ) ;
fwrite ( p - > seqs [ i ] , sizeof ( cf_t ) , p - > N_zc , f ) ;
fclose ( f ) ;
fclose ( f ) ;
}
}
for ( int i = 0 ; i < N_SEQS ; i + + )
for ( int i = 0 ; i < N_SEQS ; i + + ) {
{
FILE * f ;
FILE * f ;
char str [ 32 ] ;
char str [ 32 ] ;
sprintf ( str , " prach_dft_seq_%d.bin " , i ) ;
sprintf ( str , " prach_dft_seq_%d.bin " , i ) ;
f = fopen ( str , " wb " ) ;
f = fopen ( str , " wb " ) ;
fwrite ( p - > dft_seqs [ i ] , sizeof ( cf_t ) , p - > N_zc , f ) ;
fwrite ( p - > dft_seqs [ i ] , sizeof ( cf_t ) , p - > N_zc , f ) ;
fclose ( f ) ;
fclose ( f ) ;
}
}
for ( int i = 0 ; i < p - > N_roots ; i + + )
for ( int i = 0 ; i < p - > N_roots ; i + + ) {
{
FILE * f ;
FILE * f ;
char str [ 32 ] ;
char str [ 32 ] ;
sprintf ( str , " prach_root_seq_%d.bin " , i ) ;
sprintf ( str , " prach_root_seq_%d.bin " , i ) ;
f = fopen ( str , " wb " ) ;
f = fopen ( str , " wb " ) ;
fwrite ( p - > seqs [ p - > root_seqs_idx [ i ] ] , sizeof ( cf_t ) , p - > N_zc , f ) ;
fwrite ( p - > seqs [ p - > root_seqs_idx [ i ] ] , sizeof ( cf_t ) , p - > N_zc , f ) ;
fclose ( f ) ;
fclose ( f ) ;
}
}
return 0 ;
return 0 ;