Fixed AGC out of bounds gain

This commit is contained in:
Xavier Arteaga 2018-06-11 13:14:47 +02:00
parent 2d3e788d19
commit 301415a00a
18 changed files with 159 additions and 28 deletions

View File

@ -199,7 +199,12 @@ int main(int argc, char **argv) {
srslte_ue_cellsearch_set_nof_valid_frames(&cs, cell_detect_config.nof_valid_pss_frames);
}
if (cell_detect_config.init_agc) {
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc);
srslte_rf_info_t *rf_info = srslte_rf_get_info(&rf);
srslte_ue_sync_start_agc(&cs.ue_sync,
srslte_rf_set_rx_gain_wrapper,
rf_info->min_rx_gain,
rf_info->max_rx_gain,
cell_detect_config.init_agc);
}
for (freq=0;freq<nof_freqs && !go_exit;freq++) {

View File

@ -600,7 +600,12 @@ int main(int argc, char **argv) {
#ifndef DISABLE_RF
if (prog_args.rf_gain < 0) {
srslte_ue_sync_start_agc(&ue_sync, srslte_rf_set_rx_gain_th_wrapper_, cell_detect_config.init_agc);
srslte_rf_info_t *rf_info = srslte_rf_get_info(&rf);
srslte_ue_sync_start_agc(&ue_sync,
srslte_rf_set_rx_gain_th_wrapper_,
rf_info->min_rx_gain,
rf_info->max_rx_gain,
cell_detect_config.init_agc);
}
#endif
#ifdef PRINT_CHANGE_SCHEDULIGN

View File

@ -53,6 +53,8 @@ typedef enum SRSLTE_API {
typedef struct SRSLTE_API{
float bandwidth;
double gain;
double min_gain;
double max_gain;
float y_out;
bool lock;
bool isfirst;
@ -79,6 +81,8 @@ SRSLTE_API void srslte_agc_free(srslte_agc_t *q);
SRSLTE_API void srslte_agc_reset(srslte_agc_t *q);
SRSLTE_API void srslte_agc_set_gain_range(srslte_agc_t *q, double min_gain, double max_gain);
SRSLTE_API void srslte_agc_set_bandwidth(srslte_agc_t *q,
float bandwidth);

View File

@ -55,6 +55,14 @@ typedef struct {
float iq_q;
} srslte_rf_cal_t;
typedef struct {
double min_tx_gain;
double max_tx_gain;
double min_rx_gain;
double max_rx_gain;
} srslte_rf_info_t;
typedef struct {
enum {
SRSLTE_RF_ERROR_LATE,
@ -125,6 +133,8 @@ SRSLTE_API double srslte_rf_get_rx_gain(srslte_rf_t *h);
SRSLTE_API double srslte_rf_get_tx_gain(srslte_rf_t *h);
SRSLTE_API srslte_rf_info_t *srslte_rf_get_info(srslte_rf_t *h);
SRSLTE_API void srslte_rf_suppress_stdout(srslte_rf_t *h);
SRSLTE_API void srslte_rf_register_error_handler(srslte_rf_t *h,

View File

@ -199,7 +199,9 @@ SRSLTE_API void srslte_ue_sync_reset(srslte_ue_sync_t *q);
SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q,
double (set_gain_callback)(void*, double),
float init_gain_value);
double min_gain,
double max_gain,
double init_gain_value);
SRSLTE_API uint32_t srslte_ue_sync_sf_len(srslte_ue_sync_t *q);

View File

@ -115,6 +115,7 @@ class radio {
float get_tx_gain();
float get_rx_gain();
srslte_rf_info_t *get_info();
float get_max_tx_power();
float set_tx_power(float power);

View File

@ -45,6 +45,8 @@ int srslte_agc_init_acc(srslte_agc_t *q, srslte_agc_mode_t mode, uint32_t nof_fr
bzero(q, sizeof(srslte_agc_t));
q->mode = mode;
q->nof_frames = nof_frames;
q->max_gain = 90.0;
q->min_gain = 0.0;
if (nof_frames > 0) {
q->y_tmp = srslte_vec_malloc(sizeof(float) * nof_frames);
if (!q->y_tmp) {
@ -86,6 +88,13 @@ void srslte_agc_reset(srslte_agc_t *q) {
}
}
void srslte_agc_set_gain_range(srslte_agc_t *q, double min_gain, double max_gain) {
if (q) {
q->min_gain = min_gain;
q->max_gain = max_gain;
}
}
void srslte_agc_set_bandwidth(srslte_agc_t *q, float bandwidth) {
q->bandwidth = bandwidth;
}
@ -116,19 +125,23 @@ void srslte_agc_lock(srslte_agc_t *q, bool enable) {
void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) {
if (!q->lock) {
float gain_db = 10*log10(q->gain);
float gain_uhd_db = 50.0;
//float gain_uhd = 1.0;
double gain_db = 10.0 * log10(q->gain);
double gain_uhd_db = 50.0;
float y = 0;
// Apply current gain to input signal
if (!q->uhd_handler) {
srslte_vec_sc_prod_cfc(signal, q->gain, signal, len);
} else {
if (gain_db < 0) {
gain_db = 5.0;
}
if (isinf(gain_db) || isnan(gain_db)) {
gain_db = 40.0;
if (gain_db < q->min_gain) {
gain_db = q->min_gain + 5.0;
INFO("Warning: Rx signal strength is too high. Forcing minimum Rx gain %.2fdB\n", gain_db);
} else if (gain_db > q->max_gain) {
gain_db = q->max_gain;
INFO("Warning: Rx signal strength is too weak. Forcing maximum Rx gain %.2fdB\n", gain_db);
} else if (isinf(gain_db) || isnan(gain_db)) {
gain_db = (q->min_gain + q->max_gain) / 2.0;
INFO("Warning: AGC went to an unknown state. Setting Rx gain to %.2fdB\n", gain_db);
} else {
gain_uhd_db = q->set_gain_callback(q->uhd_handler, gain_db);
q->gain = pow(10, gain_uhd_db/10);

View File

@ -45,6 +45,7 @@ typedef struct {
int16_t tx_buffer[CONVERT_BUFFER_SIZE];
bool rx_stream_enabled;
bool tx_stream_enabled;
srslte_rf_info_t info;
} rf_blade_handler_t;
srslte_rf_error_handler_t blade_error_handler = NULL;
@ -220,7 +221,14 @@ int rf_blade_open(char *args, void **h)
return status;
}
handler->rx_stream_enabled = false;
handler->tx_stream_enabled = false;
handler->tx_stream_enabled = false;
/* Set info structure */
handler->info.min_tx_gain = BLADERF_TXVGA2_GAIN_MIN;
handler->info.max_tx_gain = BLADERF_TXVGA2_GAIN_MAX;
handler->info.min_rx_gain = BLADERF_RXVGA2_GAIN_MIN;
handler->info.max_rx_gain = BLADERF_RXVGA2_GAIN_MAX;
return 0;
}
@ -336,6 +344,19 @@ double rf_blade_get_tx_gain(void *h)
return gain; // Add txvga1
}
srslte_rf_info_t *rf_blade_get_info(void *h)
{
srslte_rf_info_t *info = NULL;
if (h) {
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
info = &handler->info;
}
return info;
}
double rf_blade_set_rx_freq(void *h, double freq)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;

View File

@ -76,6 +76,8 @@ SRSLTE_API double rf_blade_get_rx_gain(void *h);
SRSLTE_API double rf_blade_get_tx_gain(void *h);
SRSLTE_API srslte_rf_info_t *rf_blade_get_info(void *h);
SRSLTE_API void rf_blade_suppress_stdout(void *h);
SRSLTE_API void rf_blade_register_error_handler(void *h,

View File

@ -47,6 +47,7 @@ typedef struct {
double (*srslte_rf_set_tx_gain)(void *h, double gain);
double (*srslte_rf_get_rx_gain)(void *h);
double (*srslte_rf_get_tx_gain)(void *h);
srslte_rf_info_t *(*srslte_rf_get_info)(void *h);
double (*srslte_rf_set_rx_freq)(void *h, double freq);
double (*srslte_rf_set_tx_srate)(void *h, double freq);
double (*srslte_rf_set_tx_freq)(void *h, double freq);
@ -93,6 +94,7 @@ static rf_dev_t dev_uhd = {
rf_uhd_set_tx_gain,
rf_uhd_get_rx_gain,
rf_uhd_get_tx_gain,
rf_uhd_get_info,
rf_uhd_set_rx_freq,
rf_uhd_set_tx_srate,
rf_uhd_set_tx_freq,
@ -132,6 +134,7 @@ static rf_dev_t dev_blade = {
rf_blade_set_tx_gain,
rf_blade_get_rx_gain,
rf_blade_get_tx_gain,
rf_blade_get_info,
rf_blade_set_rx_freq,
rf_blade_set_tx_srate,
rf_blade_set_tx_freq,
@ -170,6 +173,7 @@ static rf_dev_t dev_soapy = {
rf_soapy_set_tx_gain,
rf_soapy_get_rx_gain,
rf_soapy_get_tx_gain,
rf_soapy_get_info,
rf_soapy_set_rx_freq,
rf_soapy_set_tx_srate,
rf_soapy_set_tx_freq,

View File

@ -227,6 +227,15 @@ double srslte_rf_get_tx_gain(srslte_rf_t *rf)
return ((rf_dev_t*) rf->dev)->srslte_rf_get_tx_gain(rf->handler);
}
srslte_rf_info_t *srslte_rf_get_info(srslte_rf_t *rf) {
srslte_rf_info_t *ret = NULL;
if (((rf_dev_t*) rf->dev)->srslte_rf_get_info) {
ret = ((rf_dev_t*) rf->dev)->srslte_rf_get_info(rf->handler);
}
return ret;
}
double srslte_rf_set_rx_freq(srslte_rf_t *rf, double freq)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_set_rx_freq(rf->handler, freq);

View File

@ -46,6 +46,7 @@ typedef struct {
SoapySDRStream *txStream;
bool tx_stream_active;
bool rx_stream_active;
srslte_rf_info_t info;
} rf_soapy_handler_t;
@ -259,6 +260,14 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
printf(" - %s\n", sensors[i]);
}
/* Set static radio info */
SoapySDRRange tx_range = SoapySDRDevice_getGainRange(handler->device, SOAPY_SDR_TX, 0);
SoapySDRRange rx_range = SoapySDRDevice_getGainRange(handler->device, SOAPY_SDR_RX, 0);
handler->info.min_tx_gain = tx_range.minimum;
handler->info.max_tx_gain = tx_range.maximum;
handler->info.min_rx_gain = rx_range.minimum;
handler->info.max_rx_gain = rx_range.maximum;
return SRSLTE_SUCCESS;
}
@ -361,6 +370,17 @@ double rf_soapy_get_tx_gain(void *h)
}
srslte_rf_info_t * rf_soapy_get_info(void *h)
{
srslte_rf_info_t *info = NULL;
if (h) {
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
info = &handler->info;
}
return info;
}
double rf_soapy_set_rx_freq(void *h, double freq)
{
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;

View File

@ -75,6 +75,8 @@ SRSLTE_API double rf_soapy_set_tx_gain(void *h,
SRSLTE_API double rf_soapy_get_tx_gain(void *h);
SRSLTE_API srslte_rf_info_t *rf_soapy_get_info(void *h);
SRSLTE_API void rf_soapy_suppress_stdout(void *h);
SRSLTE_API void rf_soapy_register_error_handler(void *h, srslte_rf_error_handler_t error_handler);

View File

@ -46,7 +46,7 @@ typedef struct {
uhd_rx_metadata_handle rx_md, rx_md_first;
uhd_tx_metadata_handle tx_md;
uhd_meta_range_handle rx_gain_range;
srslte_rf_info_t info;
size_t rx_nof_samples;
size_t tx_nof_samples;
double tx_rate;
@ -572,9 +572,20 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
uhd_rx_streamer_max_num_samps(handler->rx_stream, &handler->rx_nof_samples);
uhd_tx_streamer_max_num_samps(handler->tx_stream, &handler->tx_nof_samples);
uhd_meta_range_make(&handler->rx_gain_range);
uhd_usrp_get_rx_gain_range(handler->usrp, "", 0, handler->rx_gain_range);
uhd_meta_range_handle rx_gain_range = NULL;
uhd_meta_range_make(&rx_gain_range);
uhd_usrp_get_rx_gain_range(handler->usrp, "", 0, rx_gain_range);
uhd_meta_range_start(rx_gain_range, &handler->info.min_rx_gain);
uhd_meta_range_stop(rx_gain_range, &handler->info.max_rx_gain);
uhd_meta_range_free(&rx_gain_range);
uhd_meta_range_handle tx_gain_range = NULL;
uhd_meta_range_make(&tx_gain_range);
uhd_usrp_get_tx_gain_range(handler->usrp, "", 0, tx_gain_range);
uhd_meta_range_start(tx_gain_range, &handler->info.min_tx_gain);
uhd_meta_range_stop(tx_gain_range, &handler->info.max_tx_gain);
uhd_meta_range_free(&tx_gain_range);
// Make metadata objects for RX/TX
uhd_rx_metadata_make(&handler->rx_md);
@ -582,13 +593,7 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
uhd_tx_metadata_make(&handler->tx_md, false, 0, 0, false, false);
// Set starting gain to half maximum in case of using AGC
uhd_meta_range_handle gain_range;
uhd_meta_range_make(&gain_range);
uhd_usrp_get_rx_gain_range(handler->usrp, "", 0, gain_range);
double max_gain;
uhd_meta_range_stop(gain_range, &max_gain);
rf_uhd_set_rx_gain(handler, max_gain*0.7);
uhd_meta_range_free(&gain_range);
rf_uhd_set_rx_gain(handler, handler->info.max_tx_gain*0.7);
#if HAVE_ASYNC_THREAD
if (start_async_thread) {
@ -620,7 +625,6 @@ int rf_uhd_close(void *h)
uhd_tx_metadata_free(&handler->tx_md);
uhd_rx_metadata_free(&handler->rx_md_first);
uhd_rx_metadata_free(&handler->rx_md);
uhd_meta_range_free(&handler->rx_gain_range);
handler->async_thread_running = false;
pthread_join(handler->async_thread, NULL);
@ -722,6 +726,16 @@ double rf_uhd_get_tx_gain(void *h)
return gain;
}
srslte_rf_info_t *rf_uhd_get_info(void *h)
{
srslte_rf_info_t *info = NULL;
if (h) {
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
info = &handler->info;
}
return info;
}
double rf_uhd_set_rx_freq(void *h, double freq)
{
uhd_tune_request_t tune_request = {

View File

@ -81,6 +81,8 @@ SRSLTE_API double rf_uhd_get_rx_gain(void *h);
SRSLTE_API double rf_uhd_get_tx_gain(void *h);
SRSLTE_API srslte_rf_info_t *rf_uhd_get_info(void *h);
SRSLTE_API void rf_uhd_suppress_stdout(void *h);
SRSLTE_API void rf_uhd_register_error_handler(void *h, srslte_rf_error_handler_t error_handler);

View File

@ -140,11 +140,15 @@ void srslte_ue_sync_reset(srslte_ue_sync_t *q) {
q->frame_find_cnt = 0;
}
int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(void*, double), float init_gain_value) {
int srslte_ue_sync_start_agc(srslte_ue_sync_t *q,
double (set_gain_callback)(void *, double),
double min_gain,
double max_gain,
double init_gain_value) {
int n = srslte_agc_init_uhd(&q->agc, SRSLTE_AGC_MODE_PEAK_AMPLITUDE, 0, set_gain_callback, q->stream);
q->do_agc = n==0?true:false;
if (q->do_agc) {
srslte_agc_set_gain_range(&q->agc, min_gain, max_gain);
srslte_agc_set_gain(&q->agc, init_gain_value);
srslte_ue_sync_set_agc_period(q, 4);
}

View File

@ -470,6 +470,9 @@ void radio::register_error_handler(srslte_rf_error_handler_t h)
srslte_rf_register_error_handler(&rf_device, h);
}
srslte_rf_info_t *radio::get_info() {
return srslte_rf_get_info(&rf_device);
}
}

View File

@ -625,7 +625,12 @@ void phch_recv::set_agc_enable(bool enable)
do_agc = enable;
if (do_agc) {
if (running && radio_h) {
srslte_ue_sync_start_agc(&ue_sync, callback_set_rx_gain, radio_h->get_rx_gain());
srslte_rf_info_t *rf_info = radio_h->get_info();
srslte_ue_sync_start_agc(&ue_sync,
callback_set_rx_gain,
rf_info->min_rx_gain,
rf_info->max_rx_gain,
radio_h->get_rx_gain());
search_p.set_agc_enable(true);
} else {
fprintf(stderr, "Error setting AGC: PHY not initiatec\n");
@ -893,7 +898,12 @@ float phch_recv::search::get_last_cfo()
void phch_recv::search::set_agc_enable(bool enable) {
if (enable) {
srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, p->radio_h->get_rx_gain());
srslte_rf_info_t *rf_info = p->radio_h->get_info();
srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync,
callback_set_rx_gain,
rf_info->min_rx_gain,
rf_info->max_rx_gain,
p->radio_h->get_rx_gain());
} else {
fprintf(stderr, "Error stop AGC not implemented\n");
}