@ -12,67 +12,64 @@
# include "uhd.h"
# include "uhd_utils.h"
int nof_slots = 1000 ;
# define MHZ 1000000
# define SAMP_FREQ 1920000
# define RSSI_FS 1000000
# define FLEN 9600
# define FLEN_PERIOD 0.005
# define RSSI_DECIM 20
# define IS_SIGNAL(i) (10*log10f(rssi[i]) + 30 > rssi_threshold)
int band , earfcn = - 1 ;
float pss_threshold = 15.0 ;
int earfcn_start , earfcn_end = - 1 ;
float rssi_threshold = - 42.0 ;
float find_threshold = 40.0 , track_threshold = 8.0 ;
int earfcn_start = - 1 , earfcn_end = - 1 ;
float rssi_threshold = - 30.0 ;
int max_track_lost = 9 ;
int nof_frames_find = 8 , nof_frames_track = 100 , nof_samples_rssi = 50000 ;
int track_len = 500 ;
cf_t * input_buffer ;
float * cfo_v ;
int * idx_v ;
int * idx_v , * idx_valid , * t ;
float * p2a_v ;
void * uhd ;
int nof_bands ;
int force_N_id_2 ;
float gain = 30.0 ;
float gain = 20.0 ;
# define MAX_EARFCN 1000
lte_earfcn_t channels [ MAX_EARFCN ] ;
float rssi [ MAX_EARFCN ] ;
float rssi_d [ MAX_EARFCN / RSSI_DECIM ] ;
float freqs [ MAX_EARFCN ] ;
float cfo [ MAX_EARFCN ] ;
float p2a [ MAX_EARFCN ] ;
# define MHZ 1000000
# define SAMP_FREQ 1920000
# define RSSI_FS 1000000
# define RSSI_NSAMP 50000
# define FLEN 9600
# define FLEN_PERIOD 0.005
# define IS_SIGNAL(i) (10*log10f(rssi[i]) + 30 > rssi_threshold)
enum sync_state { INIT , FIND , TRACK , DONE } ;
void print_to_matlab ( ) ;
void usage ( char * prog ) {
printf ( " Usage: %s [se nvtr ] -b band\n " , prog ) ;
printf ( " \t -s earfcn_start [Default %d]\n " , earfcn_start ) ;
printf ( " Usage: %s [seRrFfTtgv] -b band \n " , prog ) ;
printf ( " \t -s earfcn_start [Default All] \n " ) ;
printf ( " \t -e earfcn_end [Default All] \n " ) ;
printf ( " \t -n number of frames [Default %d] \n " , nof_slots ) ;
printf ( " \t -v [set verbose to debug, default none] \n " ) ;
printf ( " \t -t pss_threshold [Default %.2f] \n " , pss_threshold ) ;
printf ( " \t -R rssi_nof_samples [Default %d] \n " , nof_samples_rssi ) ;
printf ( " \t -r rssi_threshold [Default %.2f dBm] \n " , rssi_threshold ) ;
printf ( " \t -f force_N_id_2 [Default no] \n " ) ;
printf ( " \t -g gain [Default no %.2f dB] \n " , gain ) ;
printf ( " \t -F pss_find_nof_frames [Default %d] \n " , nof_frames_find ) ;
printf ( " \t -f pss_find_threshold [Default %.2f] \n " , find_threshold ) ;
printf ( " \t -T pss_track_nof_frames [Default %d] \n " , nof_frames_track ) ;
printf ( " \t -t pss_track_threshold [Default %.2f] \n " , track_threshold ) ;
printf ( " \t -l pss_track_len [Default %d] \n " , track_len ) ;
printf ( " \t -g gain [Default %.2f dB] \n " , gain ) ;
printf ( " \t -v [set verbose to debug, default none] \n " ) ;
}
void parse_args ( int argc , char * * argv ) {
int opt ;
while ( ( opt = getopt ( argc , argv , " gfrtbsenv " ) ) ! = - 1 ) {
while ( ( opt = getopt ( argc , argv , " bseRrFfTtg v" ) ) ! = - 1 ) {
switch ( opt ) {
case ' g ' :
gain = atof ( argv [ optind ] ) ;
break ;
case ' f ' :
force_N_id_2 = atoi ( argv [ optind ] ) ;
break ;
case ' t ' :
pss_threshold = atof ( argv [ optind ] ) ;
break ;
case ' r ' :
rssi_threshold = - atof ( argv [ optind ] ) ;
break ;
case ' b ' :
band = atoi ( argv [ optind ] ) ;
break ;
@ -82,8 +79,26 @@ void parse_args(int argc, char **argv) {
case ' e ' :
earfcn_end = atoi ( argv [ optind ] ) ;
break ;
case ' n ' :
nof_slots = atoi ( argv [ optind ] ) ;
case ' R ' :
nof_samples_rssi = atoi ( argv [ optind ] ) ;
break ;
case ' r ' :
rssi_threshold = - atof ( argv [ optind ] ) ;
break ;
case ' F ' :
nof_frames_find = atoi ( argv [ optind ] ) ;
break ;
case ' f ' :
find_threshold = atof ( argv [ optind ] ) ;
break ;
case ' T ' :
nof_frames_track = atoi ( argv [ optind ] ) ;
break ;
case ' t ' :
track_threshold = atof ( argv [ optind ] ) ;
break ;
case ' g ' :
gain = atof ( argv [ optind ] ) ;
break ;
case ' v ' :
verbose + + ;
@ -103,17 +118,27 @@ int base_init(int frame_length) {
exit ( - 1 ) ;
}
idx_v = malloc ( nof_ slots * sizeof ( int ) ) ;
idx_v = malloc ( nof_ frames_track * sizeof ( int ) ) ;
if ( ! idx_v ) {
perror ( " malloc " ) ;
exit ( - 1 ) ;
}
cfo_v = malloc ( nof_slots * sizeof ( float ) ) ;
idx_valid = malloc ( nof_frames_track * sizeof ( int ) ) ;
if ( ! idx_valid ) {
perror ( " malloc " ) ;
exit ( - 1 ) ;
}
t = malloc ( nof_frames_track * sizeof ( int ) ) ;
if ( ! t ) {
perror ( " malloc " ) ;
exit ( - 1 ) ;
}
cfo_v = malloc ( nof_frames_track * sizeof ( float ) ) ;
if ( ! cfo_v ) {
perror ( " malloc " ) ;
exit ( - 1 ) ;
}
p2a_v = malloc ( nof_slots * sizeof ( float ) ) ;
p2a_v = malloc ( nof_ frames_track * sizeof ( float ) ) ;
if ( ! p2a_v ) {
perror ( " malloc " ) ;
exit ( - 1 ) ;
@ -137,6 +162,8 @@ void base_free() {
uhd_close ( & uhd ) ;
free ( input_buffer ) ;
free ( idx_v ) ;
free ( idx_valid ) ;
free ( t ) ;
free ( cfo_v ) ;
free ( p2a_v ) ;
}
@ -158,14 +185,61 @@ float mean_valid(int *idx_v, float *x, int nof_frames) {
}
}
int main ( int argc , char * * argv ) {
int frame_cnt ;
int preprocess_idx ( int * in , int * out , int * period , int len ) {
int i , n ;
n = 0 ;
for ( i = 0 ; i < len ; i + + ) {
if ( in [ i ] ! = - 1 ) {
out [ n ] = in [ i ] ;
period [ n ] = i ;
n + + ;
}
}
return n ;
}
int rssi_scan ( ) {
int n = 0 ;
int i ;
int nsamples ;
if ( nof_bands > 100 ) {
/* scan every Mhz, that is 10 freqs */
for ( i = 0 ; i < nof_bands ; i + = RSSI_DECIM ) {
freqs [ n ] = channels [ i ] . fd * MHZ ;
n + + ;
}
if ( uhd_rssi_scan ( uhd , freqs , rssi_d , n , ( double ) RSSI_FS , nof_samples_rssi ) ) {
fprintf ( stderr , " Error while doing RSSI scan \n " ) ;
return - 1 ;
}
/* linearly interpolate the rssi vector */
interp_linear_f ( rssi_d , rssi , RSSI_DECIM , n ) ;
} else {
for ( i = 0 ; i < nof_bands ; i + + ) {
freqs [ i ] = channels [ i ] . fd * MHZ ;
}
if ( uhd_rssi_scan ( uhd , freqs , rssi , nof_bands , ( double ) RSSI_FS , nof_samples_rssi ) ) {
fprintf ( stderr , " Error while doing RSSI scan \n " ) ;
return - 1 ;
}
n = nof_bands ;
}
return n ;
}
int main ( int argc , char * * argv ) {
int frame_cnt , valid_frames ;
int freq ;
int cell_id ;
sync_t synch ;
sync_t s find, strack ;
float max_peak_to_avg ;
float sfo ;
int find_idx , track_idx , last_found ;
enum sync_state state ;
int n ;
filesink_t fs ;
if ( argc < 3 ) {
usage ( argv [ 0 ] ) ;
@ -179,113 +253,162 @@ int main(int argc, char **argv) {
exit ( - 1 ) ;
}
if ( sync_init ( & s ynch ) ) {
if ( sync_init ( & s find, FLEN ) ) {
fprintf ( stderr , " Error initiating PSS/SSS \n " ) ;
exit ( - 1 ) ;
}
sync_set_threshold ( & synch , pss_threshold ) ;
sync_pss_det_peakmean ( & synch ) ;
sync_pss_det_peakmean ( & sfind ) ;
if ( force_N_id_2 ! = - 1 ) {
sync_force_N_id_2 ( & synch , force_N_id_2 ) ;
if ( sync_init ( & strack , track_len ) ) {
fprintf ( stderr , " Error initiating PSS/SSS \n " ) ;
exit ( - 1 ) ;
}
sync_pss_det_peakmean ( & strack ) ;
nof_bands = lte_band_get_fd_band ( band , channels , earfcn_start , earfcn_end , MAX_EARFCN ) ;
printf ( " RSSI scan: %d freqs in band %d \n " , nof_bands , band ) ;
for ( i = 0 ; i < nof_bands ; i + + ) {
freqs [ i ] = channels [ i ] . fd * MHZ ;
}
printf ( " RSSI scan: %d freqs in band %d, RSSI threshold %.2f dBm \n " , nof_bands , band , rssi_threshold ) ;
if ( uhd_rssi_scan ( uhd , freqs , rssi , nof_bands , ( double ) RSSI_FS , RSSI_NSAMP ) ) {
fprintf ( stderr , " Error while doing RSSI scan \n " ) ;
n = rssi_scan ( ) ;
if ( n = = - 1 ) {
exit ( - 1 ) ;
}
printf ( " \n Done. Starting PSS search \n " ) ;
printf ( " \n Done. Starting PSS search on %d channels \n " , n ) ;
usleep ( 500000 ) ;
printf ( " Setting sampling frequency %.2f MHz \n " , ( float ) SAMP_FREQ / MHZ ) ;
INFO ( " Setting sampling frequency %.2f MHz \n " , ( float ) SAMP_FREQ / MHZ ) ;
uhd_set_rx_srate ( uhd , SAMP_FREQ ) ;
uhd_set_rx_gain ( uhd , gain ) ;
print_to_matlab ( ) ;
int first = 1 ;
for ( i = 0 ; i < nof_bands ; i + + ) {
filesink_init ( & fs , " test.dat " , COMPLEX_FLOAT_BIN ) ;
freq = 0 ;
state = INIT ;
while ( freq < nof_bands ) {
/* scan only bands above rssi_threshold */
if ( IS_SIGNAL ( i ) ) {
uhd_set_rx_freq ( uhd , ( double ) channels [ i ] . fd * MHZ ) ;
uhd_rx_wait_lo_locked ( uhd ) ;
if ( ! IS_SIGNAL ( freq ) ) {
INFO ( " [%3d/%d]: Skipping EARFCN %d %.2f MHz RSSI %.2f dB \n " , freq , nof_bands ,
channels [ freq ] . id , channels [ freq ] . fd , 10 * log10f ( rssi [ freq ] ) + 30 ) ;
freq + + ;
} else {
if ( state = = TRACK | | state = = FIND ) {
uhd_recv ( uhd , & input_buffer [ FLEN ] , FLEN , 1 ) ;
}
switch ( state ) {
case INIT :
DEBUG ( " Stopping receiver... \n " , 0 ) ;
uhd_stop_rx_stream ( uhd ) ;
/* set freq */
uhd_set_rx_freq ( uhd , ( double ) channels [ freq ] . fd * MHZ ) ;
uhd_rx_wait_lo_locked ( uhd ) ;
DEBUG ( " Set freq to %.3f MHz \n " , ( double ) channels [ freq ] . fd ) ;
if ( first ) {
INFO ( " Starting receiver... \n " , 0 ) ;
DEBUG ( " Starting receiver... \n " , 0 ) ;
uhd_start_rx_stream ( uhd ) ;
first = 0 ;
}
frame_cnt = 0 ;
nsamples = 0 ;
max_peak_to_avg = - 99 ;
nsamples + = uhd_recv ( uhd , input_buffer , FLEN , 1 ) ;
cell_id = - 1 ;
while ( frame_cnt < nof_slots ) {
if ( frame_cnt ) {
nsamples + = uhd_recv ( uhd , & input_buffer [ FLEN ] , FLEN , 1 ) ;
/* init variables */
frame_cnt = 0 ;
max_peak_to_avg = - 99 ;
cell_id = - 1 ;
/* receive first frame */
uhd_recv ( uhd , input_buffer , FLEN , 1 ) ;
/* set find_threshold and go to FIND state */
sync_set_threshold ( & sfind , find_threshold ) ;
sync_force_N_id_2 ( & sfind , - 1 ) ;
state = FIND ;
break ;
case FIND :
/* find peak in all frame */
find_idx = sync_run ( & sfind , input_buffer , FLEN ) ;
DEBUG ( " [%3d/%d]: PAR=%.2f \n " , freq , nof_bands , sync_get_peak_to_avg ( & sfind ) ) ;
if ( find_idx ! = - 1 ) {
/* if found peak, go to track and set lower threshold */
frame_cnt = - 1 ;
last_found = 0 ;
sync_set_threshold ( & strack , track_threshold ) ;
sync_force_N_id_2 ( & strack , sync_get_N_id_2 ( & sfind ) ) ;
state = TRACK ;
INFO ( " [%3d/%d]: EARFCN %d Freq. %.2f MHz PSS found PAR %.2f dB \n " , freq , nof_bands ,
channels [ freq ] . id , channels [ freq ] . fd ,
10 * log10f ( sync_get_peak_to_avg ( & sfind ) ) ) ;
} else {
if ( frame_cnt > = nof_frames_find ) {
state = INIT ;
printf ( " [%3d/%d]: EARFCN %d Freq. %.2f MHz No PSS found \r " , freq , nof_bands ,
channels [ freq ] . id , channels [ freq ] . fd , frame_cnt - last_found ) ;
if ( VERBOSE_ISINFO ( ) ) {
printf ( " \n " ) ;
}
freq + + ;
}
}
break ;
case TRACK :
INFO ( " Tracking PSS find_idx %d offset %d \n " , find_idx , find_idx + track_len ) ;
idx_v [ frame_cnt ] = sync_run ( & synch , input_buffer , frame_cnt ? FLEN : 0 ) ;
p2a_v [ frame_cnt ] = sync_get_peak_to_avg ( & synch ) ;
if ( idx_v [ frame_cnt ] ! = - 1 ) {
/* save cell id for the best peak-to-avg */
if ( p2a_v [ frame_cnt ] > max_peak_to_avg ) {
max_peak_to_avg = p2a_v [ frame_cnt ] ;
cell_id = sync_get_cell_id ( & synch ) ;
}
cfo_v [ frame_cnt ] = sync_get_cfo ( & synch ) ;
filesink_write ( & fs , & input_buffer [ FLEN + find_idx + track_len ] , track_len ) ;
track_idx = sync_run ( & strack , input_buffer , FLEN + find_idx - track_len ) ;
p2a_v [ frame_cnt ] = sync_get_peak_to_avg ( & strack ) ;
/* save cell id for the best peak-to-avg */
if ( p2a_v [ frame_cnt ] > max_peak_to_avg ) {
max_peak_to_avg = p2a_v [ frame_cnt ] ;
cell_id = sync_get_cell_id ( & strack ) ;
}
if ( track_idx ! = - 1 ) {
cfo_v [ frame_cnt ] = sync_get_cfo ( & strack ) ;
last_found = frame_cnt ;
find_idx + = track_idx - track_len ;
idx_v [ frame_cnt ] = find_idx ;
} else {
idx_v [ frame_cnt ] = - 1 ;
cfo_v [ frame_cnt ] = 0.0 ;
}
if ( frame_cnt ) {
memcpy ( input_buffer , & input_buffer [ FLEN ] , FLEN * sizeof ( cf_t ) ) ;
/* if we missed to many PSS it is not a cell, next freq */
if ( frame_cnt - last_found > max_track_lost ) {
INFO ( " \n [%3d/%d]: EARFCN %d Freq. %.2f MHz %d frames lost \n " , freq , nof_bands ,
channels [ freq ] . id , channels [ freq ] . fd , frame_cnt - last_found ) ;
state = INIT ;
freq + + ;
} else if ( frame_cnt > = nof_frames_track ) {
state = DONE ;
}
if ( VERBOSE_ISINFO ( ) ) {
printf ( " [%4d] - idx: %5d \t peak-to-avg: %3.2f \t cfo=%.3f \r " , frame_cnt ,
idx_v [ frame_cnt ] , p2a_v [ frame_cnt ] , cfo_v [ frame_cnt ] ) ;
}
frame_cnt + + ;
}
cfo [ i ] = mean_valid ( idx_v , cfo_v , nof_slots ) ;
p2a [ i ] = sum_r ( p2a_v , nof_slots ) / nof_slots ;
if ( channels [ i ] . id = = 1900
| | channels [ i ] . id = = 1901 ) {
vec_fprint_i ( stdout , idx_v , nof_slots ) ;
break ;
case DONE :
cfo [ freq ] = mean_valid ( idx_v , cfo_v , frame_cnt ) ;
p2a [ freq ] = mean_valid ( idx_v , p2a_v , frame_cnt ) ;
valid_frames = preprocess_idx ( idx_v , idx_valid , t , frame_cnt ) ;
sfo = sfo_estimate_period ( idx_valid , t , valid_frames , FLEN_PERIOD ) ;
printf ( " \n [%3d/%d]: FOUND EARFCN %d Freq. %.2f MHz. "
" PAR %2.2f dB, CFO=%+.2f KHz, SFO=%+2.3f KHz, CELL_ID=%3d \n " , freq , nof_bands ,
channels [ freq ] . id , channels [ freq ] . fd ,
10 * log10f ( p2a [ freq ] ) , cfo [ freq ] * 15 , sfo / 1000 , cell_id ) ;
state = INIT ;
freq + + ;
break ;
}
sfo = sfo_estimate ( idx_v , nof_slots , FLEN_PERIOD ) ;
if ( VERBOSE_ISINFO ( ) ) {
printf ( " \n " ) ;
if ( state = = TRACK | | ( state = = FIND & & frame_cnt ) ) {
memcpy ( input_buffer , & input_buffer [ FLEN ] , FLEN * sizeof ( cf_t ) ) ;
}
printf ( " [%3d/%d]: EARFCN %d Freq. %.2f MHz, "
" RSSI %3.2f dBm, PSS %2.2f dB, CFO=%+2.1f KHz, SFO=%+2.1f KHz, CELL_ID=%3d \n " , i , nof_bands ,
channels [ i ] . id , channels [ i ] . fd , 10 * log10f ( rssi [ i ] ) + 30 ,
10 * log10f ( p2a [ i ] ) , cfo [ i ] * 15 , sfo / 1000 , cell_id ) ;
print_to_matlab ( ) ;
} else {
INFO ( " [%3d/%d]: EARFCN %d Freq. %.2f MHz. RSSI below threshold (%3.2f < %3.2f dBm) \n " ,
i , nof_bands , channels [ i ] . id , channels [ i ] . fd , 10 * log10f ( rssi [ i ] ) + 30 , rssi_threshold ) ;
frame_cnt + + ;
}
}
print_to_matlab ( ) ;
sync_free ( & s ynch ) ;
sync_free ( & sfind ) ;
base_free ( ) ;
printf ( " Done \n " ) ;
printf ( " \n \n Done \n " ) ;
exit ( 0 ) ;
}
@ -309,6 +432,13 @@ void print_to_matlab() {
}
fprintf ( f , " ]; \n " ) ;
fprintf ( f , " rssi_d=[ " ) ;
for ( i = 0 ; i < nof_bands / RSSI_DECIM ; i + + ) {
fprintf ( f , " %g, " , rssi_d [ i ] ) ;
}
fprintf ( f , " ]; \n " ) ;
/*
fprintf ( f , " cfo=[ " ) ;
for ( i = 0 ; i < nof_bands ; i + + ) {