mirror of https://github.com/PentHertz/srsLTE.git
Fixing AGC
This commit is contained in:
parent
f8405a2c08
commit
ee78f0111b
|
@ -39,6 +39,9 @@ extern "C" {
|
||||||
SRSLTE_API int cuhd_open(char *args,
|
SRSLTE_API int cuhd_open(char *args,
|
||||||
void **handler);
|
void **handler);
|
||||||
|
|
||||||
|
SRSLTE_API int cuhd_open_th(char *args,
|
||||||
|
void **handler);
|
||||||
|
|
||||||
SRSLTE_API int cuhd_close(void *h);
|
SRSLTE_API int cuhd_close(void *h);
|
||||||
|
|
||||||
SRSLTE_API int cuhd_start_rx_stream(void *h);
|
SRSLTE_API int cuhd_start_rx_stream(void *h);
|
||||||
|
@ -58,6 +61,9 @@ SRSLTE_API double cuhd_set_rx_srate(void *h,
|
||||||
SRSLTE_API double cuhd_set_rx_gain(void *h,
|
SRSLTE_API double cuhd_set_rx_gain(void *h,
|
||||||
double gain);
|
double gain);
|
||||||
|
|
||||||
|
SRSLTE_API double cuhd_set_rx_gain_th(void *h,
|
||||||
|
double gain);
|
||||||
|
|
||||||
SRSLTE_API double cuhd_get_rx_gain(void *h);
|
SRSLTE_API double cuhd_get_rx_gain(void *h);
|
||||||
|
|
||||||
SRSLTE_API double cuhd_set_rx_freq(void *h,
|
SRSLTE_API double cuhd_set_rx_freq(void *h,
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <uhd/usrp/multi_usrp.hpp>
|
#include <uhd/usrp/multi_usrp.hpp>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
class cuhd_handler {
|
class cuhd_handler {
|
||||||
public:
|
public:
|
||||||
|
@ -34,5 +35,11 @@ public:
|
||||||
uhd::rx_streamer::sptr rx_stream;
|
uhd::rx_streamer::sptr rx_stream;
|
||||||
bool rx_stream_enable;
|
bool rx_stream_enable;
|
||||||
uhd::tx_streamer::sptr tx_stream;
|
uhd::tx_streamer::sptr tx_stream;
|
||||||
|
|
||||||
|
// The following variables are for threaded RX gain control
|
||||||
|
pthread_t thread_gain;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
double cur_rx_gain;
|
||||||
|
double new_rx_gain;
|
||||||
};
|
};
|
||||||
|
|
|
@ -117,7 +117,36 @@ int cuhd_start_rx_stream_nsamples(void *h, uint32_t nsamples)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cuhd_open(char *args, void **h)
|
double cuhd_set_rx_gain_th(void *h, double gain)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
|
||||||
|
// round to avoid histeresis
|
||||||
|
gain = roundf(gain);
|
||||||
|
pthread_mutex_lock(&handler->mutex);
|
||||||
|
handler->new_rx_gain = gain;
|
||||||
|
pthread_cond_signal(&handler->cond);
|
||||||
|
pthread_mutex_unlock(&handler->mutex);
|
||||||
|
*/
|
||||||
|
return gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This thread listens for set_rx_gain commands to the USRP */
|
||||||
|
static void* thread_gain_fcn(void *h) {
|
||||||
|
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
|
||||||
|
while(1) {
|
||||||
|
pthread_mutex_lock(&handler->mutex);
|
||||||
|
while(handler->cur_rx_gain == handler->new_rx_gain) {
|
||||||
|
pthread_cond_wait(&handler->cond, &handler->mutex);
|
||||||
|
}
|
||||||
|
handler->cur_rx_gain = handler->new_rx_gain;
|
||||||
|
pthread_mutex_unlock(&handler->mutex);
|
||||||
|
cuhd_set_rx_gain(h, handler->cur_rx_gain);
|
||||||
|
printf("set gain to %f\n", handler->cur_rx_gain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cuhd_open_(char *args, void **h, bool create_thread_gain)
|
||||||
{
|
{
|
||||||
cuhd_handler *handler = new cuhd_handler();
|
cuhd_handler *handler = new cuhd_handler();
|
||||||
std::string _args = std::string(args);
|
std::string _args = std::string(args);
|
||||||
|
@ -139,9 +168,32 @@ int cuhd_open(char *args, void **h)
|
||||||
|
|
||||||
*h = handler;
|
*h = handler;
|
||||||
|
|
||||||
|
if (create_thread_gain) {
|
||||||
|
if (pthread_mutex_init(&handler->mutex, NULL)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (pthread_cond_init(&handler->cond, NULL)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_create(&handler->thread_gain, NULL, thread_gain_fcn, *h)) {
|
||||||
|
perror("pthread_create");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cuhd_open(char *args, void **h) {
|
||||||
|
return cuhd_open_(args, h, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cuhd_open_th(char *args, void **h) {
|
||||||
|
return cuhd_open_(args, h, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int cuhd_close(void *h)
|
int cuhd_close(void *h)
|
||||||
{
|
{
|
||||||
cuhd_stop_rx_stream(h);
|
cuhd_stop_rx_stream(h);
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
int band = -1;
|
int band = -1;
|
||||||
int earfcn_start=-1, earfcn_end = -1;
|
int earfcn_start=-1, earfcn_end = -1;
|
||||||
|
|
||||||
cell_search_cfg_t config = {100, 10, 16};
|
cell_search_cfg_t config = {100, 10, 16, true};
|
||||||
|
|
||||||
|
|
||||||
float uhd_gain = 60.0;
|
float uhd_gain = 60.0;
|
||||||
|
@ -167,6 +167,9 @@ int main(int argc, char **argv) {
|
||||||
if (config.threshold) {
|
if (config.threshold) {
|
||||||
srslte_ue_cellsearch_set_threshold(&cs, config.threshold);
|
srslte_ue_cellsearch_set_threshold(&cs, config.threshold);
|
||||||
}
|
}
|
||||||
|
if (config.do_agc) {
|
||||||
|
srslte_ue_sync_start_agc(&cs.ue_sync, cuhd_set_rx_gain);
|
||||||
|
}
|
||||||
|
|
||||||
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000);
|
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000);
|
||||||
cuhd_set_rx_srate(uhd, SRSLTE_CS_SAMP_FREQ);
|
cuhd_set_rx_srate(uhd, SRSLTE_CS_SAMP_FREQ);
|
||||||
|
@ -183,7 +186,7 @@ int main(int argc, char **argv) {
|
||||||
srslte_cell_t cell;
|
srslte_cell_t cell;
|
||||||
cell.id = found_cells[i].cell_id;
|
cell.id = found_cells[i].cell_id;
|
||||||
cell.cp = found_cells[i].cp;
|
cell.cp = found_cells[i].cp;
|
||||||
int ret = cuhd_mib_decoder(uhd, 100, &cell);
|
int ret = cuhd_mib_decoder(uhd, &config, &cell);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Error decoding MIB\n");
|
fprintf(stderr, "Error decoding MIB\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|
|
@ -50,7 +50,7 @@ int cuhd_recv_wrapper_cs(void *h, void *data, uint32_t nsamples, srslte_timestam
|
||||||
/** This function is simply a wrapper to the ue_cell_search module for cuhd devices
|
/** This function is simply a wrapper to the ue_cell_search module for cuhd devices
|
||||||
* Return 1 if the MIB is decoded, 0 if not or -1 on error.
|
* Return 1 if the MIB is decoded, 0 if not or -1 on error.
|
||||||
*/
|
*/
|
||||||
int cuhd_mib_decoder(void *uhd, uint32_t max_nof_frames, srslte_cell_t *cell) {
|
int cuhd_mib_decoder(void *uhd, cell_search_cfg_t *config, srslte_cell_t *cell) {
|
||||||
int ret = SRSLTE_ERROR;
|
int ret = SRSLTE_ERROR;
|
||||||
srslte_ue_mib_sync_t ue_mib;
|
srslte_ue_mib_sync_t ue_mib;
|
||||||
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
|
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
|
||||||
|
@ -60,7 +60,9 @@ int cuhd_mib_decoder(void *uhd, uint32_t max_nof_frames, srslte_cell_t *cell) {
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
srslte_ue_sync_start_agc(&ue_mib.ue_sync, cuhd_set_rx_gain);
|
if (config->do_agc) {
|
||||||
|
srslte_ue_sync_start_agc(&ue_mib.ue_sync, cuhd_set_rx_gain_th);
|
||||||
|
}
|
||||||
|
|
||||||
int srate = srslte_sampling_freq_hz(SRSLTE_UE_MIB_NOF_PRB);
|
int srate = srslte_sampling_freq_hz(SRSLTE_UE_MIB_NOF_PRB);
|
||||||
INFO("Setting sampling frequency %.2f MHz for PSS search\n", (float) srate/1000000);
|
INFO("Setting sampling frequency %.2f MHz for PSS search\n", (float) srate/1000000);
|
||||||
|
@ -70,7 +72,7 @@ int cuhd_mib_decoder(void *uhd, uint32_t max_nof_frames, srslte_cell_t *cell) {
|
||||||
cuhd_start_rx_stream(uhd);
|
cuhd_start_rx_stream(uhd);
|
||||||
|
|
||||||
/* Find and decody MIB */
|
/* Find and decody MIB */
|
||||||
ret = srslte_ue_mib_sync_decode(&ue_mib, max_nof_frames, bch_payload, &cell->nof_ports, NULL);
|
ret = srslte_ue_mib_sync_decode(&ue_mib, config->max_frames_pss, bch_payload, &cell->nof_ports, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Error decoding MIB\n");
|
fprintf(stderr, "Error decoding MIB\n");
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
|
@ -109,9 +111,11 @@ int cuhd_cell_search(void *uhd, cell_search_cfg_t *config,
|
||||||
if (config->threshold) {
|
if (config->threshold) {
|
||||||
srslte_ue_cellsearch_set_threshold(&cs, config->threshold);
|
srslte_ue_cellsearch_set_threshold(&cs, config->threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
srslte_ue_sync_start_agc(&cs.ue_sync, cuhd_set_rx_gain);
|
|
||||||
|
|
||||||
|
if (config->do_agc) {
|
||||||
|
srslte_ue_sync_start_agc(&cs.ue_sync, cuhd_set_rx_gain_th);
|
||||||
|
}
|
||||||
|
|
||||||
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000);
|
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000);
|
||||||
cuhd_set_rx_srate(uhd, SRSLTE_CS_SAMP_FREQ);
|
cuhd_set_rx_srate(uhd, SRSLTE_CS_SAMP_FREQ);
|
||||||
|
|
||||||
|
@ -160,7 +164,7 @@ int cuhd_search_and_decode_mib(void *uhd, cell_search_cfg_t *config, int force_N
|
||||||
ret = cuhd_cell_search(uhd, config, force_N_id_2, cell);
|
ret = cuhd_cell_search(uhd, config, force_N_id_2, cell);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
printf("Decoding PBCH for cell %d (N_id_2=%d)\n", cell->id, cell->id%3);
|
printf("Decoding PBCH for cell %d (N_id_2=%d)\n", cell->id, cell->id%3);
|
||||||
ret = cuhd_mib_decoder(uhd, config->max_frames_pbch, cell);
|
ret = cuhd_mib_decoder(uhd, config, cell);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Could not decode PBCH from CELL ID %d\n", cell->id);
|
fprintf(stderr, "Could not decode PBCH from CELL ID %d\n", cell->id);
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
|
|
|
@ -32,10 +32,11 @@ typedef struct SRSLTE_API {
|
||||||
uint32_t max_frames_pbch; // maximum number of 5ms frames to capture for MIB decoding
|
uint32_t max_frames_pbch; // maximum number of 5ms frames to capture for MIB decoding
|
||||||
uint32_t max_frames_pss; // maximum number of 5ms frames to capture for PSS correlation
|
uint32_t max_frames_pss; // maximum number of 5ms frames to capture for PSS correlation
|
||||||
float threshold; // early-stops cell detection if mean PSR is above this value
|
float threshold; // early-stops cell detection if mean PSR is above this value
|
||||||
|
bool do_agc;
|
||||||
}cell_search_cfg_t;
|
}cell_search_cfg_t;
|
||||||
|
|
||||||
int cuhd_mib_decoder(void *uhd,
|
int cuhd_mib_decoder(void *uhd,
|
||||||
uint32_t max_nof_frames,
|
cell_search_cfg_t *config,
|
||||||
srslte_cell_t *cell);
|
srslte_cell_t *cell);
|
||||||
|
|
||||||
int cuhd_cell_search(void *uhd,
|
int cuhd_cell_search(void *uhd,
|
||||||
|
|
|
@ -103,7 +103,7 @@ void args_default(prog_args_t *args) {
|
||||||
args->uhd_args = "";
|
args->uhd_args = "";
|
||||||
args->uhd_freq = -1.0;
|
args->uhd_freq = -1.0;
|
||||||
args->uhd_freq_offset = 8000000.0;
|
args->uhd_freq_offset = 8000000.0;
|
||||||
args->uhd_gain = 60.0;
|
args->uhd_gain = -1.0;
|
||||||
args->net_port = -1;
|
args->net_port = -1;
|
||||||
args->net_address = "127.0.0.1";
|
args->net_address = "127.0.0.1";
|
||||||
args->net_port_signal = -1;
|
args->net_port_signal = -1;
|
||||||
|
@ -114,7 +114,7 @@ void usage(prog_args_t *args, char *prog) {
|
||||||
printf("Usage: %s [agpPcildnruv] -f rx_frequency (in Hz) | -i input_file\n", prog);
|
printf("Usage: %s [agpPcildnruv] -f rx_frequency (in Hz) | -i input_file\n", prog);
|
||||||
#ifndef DISABLE_UHD
|
#ifndef DISABLE_UHD
|
||||||
printf("\t-a UHD args [Default %s]\n", args->uhd_args);
|
printf("\t-a UHD args [Default %s]\n", args->uhd_args);
|
||||||
printf("\t-g UHD RX gain [Default %.2f dB]\n", args->uhd_gain);
|
printf("\t-g UHD fix RX gain [Default AGC]\n");
|
||||||
printf("\t-o UHD RX freq offset [Default %.1f MHz]\n", args->uhd_freq_offset/1000000);
|
printf("\t-o UHD RX freq offset [Default %.1f MHz]\n", args->uhd_freq_offset/1000000);
|
||||||
#else
|
#else
|
||||||
printf("\t UHD is disabled. CUHD library not available\n");
|
printf("\t UHD is disabled. CUHD library not available\n");
|
||||||
|
@ -270,12 +270,19 @@ int main(int argc, char **argv) {
|
||||||
#ifndef DISABLE_UHD
|
#ifndef DISABLE_UHD
|
||||||
if (!prog_args.input_file_name) {
|
if (!prog_args.input_file_name) {
|
||||||
printf("Opening UHD device...\n");
|
printf("Opening UHD device...\n");
|
||||||
if (cuhd_open(prog_args.uhd_args, &uhd)) {
|
if (cuhd_open_th(prog_args.uhd_args, &uhd)) {
|
||||||
fprintf(stderr, "Error opening uhd\n");
|
fprintf(stderr, "Error opening uhd\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cuhd_set_rx_gain(uhd, 50);
|
||||||
|
|
||||||
/* Set receiver gain */
|
/* Set receiver gain */
|
||||||
cuhd_set_rx_gain(uhd, prog_args.uhd_gain);
|
if (prog_args.uhd_gain > 0) {
|
||||||
|
cuhd_set_rx_gain(uhd, prog_args.uhd_gain);
|
||||||
|
} else {
|
||||||
|
cell_detect_config.do_agc = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* set receiver frequency */
|
/* set receiver frequency */
|
||||||
cuhd_set_rx_freq_offset(uhd, (double) prog_args.uhd_freq, prog_args.uhd_freq_offset);
|
cuhd_set_rx_freq_offset(uhd, (double) prog_args.uhd_freq, prog_args.uhd_freq_offset);
|
||||||
|
@ -369,7 +376,9 @@ int main(int argc, char **argv) {
|
||||||
bool decode_pdsch;
|
bool decode_pdsch;
|
||||||
int pdcch_tx=0;
|
int pdcch_tx=0;
|
||||||
|
|
||||||
srslte_ue_sync_start_agc(&ue_sync, cuhd_set_rx_gain);
|
if (prog_args.uhd_gain < 0) {
|
||||||
|
srslte_ue_sync_start_agc(&ue_sync, cuhd_set_rx_gain_th);
|
||||||
|
}
|
||||||
|
|
||||||
INFO("\nEntering main loop...\n\n", 0);
|
INFO("\nEntering main loop...\n\n", 0);
|
||||||
/* Main loop */
|
/* Main loop */
|
||||||
|
@ -461,16 +470,7 @@ int main(int argc, char **argv) {
|
||||||
pdcch_tx++;
|
pdcch_tx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
float max=-999;
|
|
||||||
for (int i=0;i<SRSLTE_SF_LEN_PRB(cell.nof_prb);i++) {
|
|
||||||
if (fabs(crealf(sf_buffer[i])) > max) {
|
|
||||||
max = fabs(crealf(sf_buffer[i]));
|
|
||||||
}
|
|
||||||
if (fabs(cimagf(sf_buffer[i])) > max) {
|
|
||||||
max = fabs(cimagf(sf_buffer[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Plot and Printf
|
// Plot and Printf
|
||||||
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
|
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
|
||||||
#ifdef STDOUT_COMPACT
|
#ifdef STDOUT_COMPACT
|
||||||
|
@ -480,14 +480,13 @@ int main(int argc, char **argv) {
|
||||||
#else
|
#else
|
||||||
printf("CFO: %+6.2f KHz, SFO: %+6.2f Khz, "
|
printf("CFO: %+6.2f KHz, SFO: %+6.2f Khz, "
|
||||||
"RSRP: %+5.1f dBm, SNR: %4.1f dB, "
|
"RSRP: %+5.1f dBm, SNR: %4.1f dB, "
|
||||||
"PDCCH-Miss: %5.2f%% (%u), PDSCH-BLER: %5.2f%% Peak: %.2f Gain: %.1f dB/%.1f\r",
|
"PDCCH-Miss: %5.2f%% (%u), PDSCH-BLER: %5.2f%% Peak: %.2f Gain: %.1f dB\r",
|
||||||
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000,
|
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000,
|
||||||
10*log10(rsrp*1000)-gain_offset,
|
10*log10(rsrp*1000)-gain_offset,
|
||||||
10*log10(snr),
|
10*log10(snr),
|
||||||
100*(1-(float) ue_dl.nof_detected/nof_trials), pdcch_tx-ue_dl.nof_detected,
|
100*(1-(float) ue_dl.nof_detected/nof_trials), pdcch_tx-ue_dl.nof_detected,
|
||||||
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total, max, cuhd_get_rx_gain(uhd),
|
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total,
|
||||||
10*log10(ue_sync.agc.gain)
|
srslte_agc_get_output_level(&ue_sync.agc), 10*log10(srslte_agc_get_gain(&ue_sync.agc)));
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,8 @@
|
||||||
|
|
||||||
#include "srslte/config.h"
|
#include "srslte/config.h"
|
||||||
|
|
||||||
#define SRSLTE_AGC_DEFAULT_TARGET 0.4
|
#define SRSLTE_AGC_DEFAULT_TARGET 0.5
|
||||||
#define SRSLTE_AGC_DEFAULT_BW (5e-2)
|
#define SRSLTE_AGC_DEFAULT_BW (2e-1)
|
||||||
|
|
||||||
typedef enum SRSLTE_API {
|
typedef enum SRSLTE_API {
|
||||||
SRSLTE_AGC_MODE_ENERGY = 0,
|
SRSLTE_AGC_MODE_ENERGY = 0,
|
||||||
|
@ -61,12 +61,18 @@ typedef struct SRSLTE_API{
|
||||||
double (*set_gain_callback) (void*,double);
|
double (*set_gain_callback) (void*,double);
|
||||||
srslte_agc_mode_t mode;
|
srslte_agc_mode_t mode;
|
||||||
float target;
|
float target;
|
||||||
|
uint32_t nof_frames;
|
||||||
|
uint32_t frame_cnt;
|
||||||
|
float *y_tmp;
|
||||||
} srslte_agc_t;
|
} srslte_agc_t;
|
||||||
|
|
||||||
SRSLTE_API int srslte_agc_init(srslte_agc_t *q, srslte_agc_mode_t mode);
|
SRSLTE_API int srslte_agc_init(srslte_agc_t *q, srslte_agc_mode_t mode);
|
||||||
|
|
||||||
|
SRSLTE_API int srslte_agc_init_acc(srslte_agc_t *q, srslte_agc_mode_t mode, uint32_t nof_frames);
|
||||||
|
|
||||||
SRSLTE_API int srslte_agc_init_uhd(srslte_agc_t *q,
|
SRSLTE_API int srslte_agc_init_uhd(srslte_agc_t *q,
|
||||||
srslte_agc_mode_t mode,
|
srslte_agc_mode_t mode,
|
||||||
|
uint32_t nof_frames,
|
||||||
double (set_gain_callback)(void*, double),
|
double (set_gain_callback)(void*, double),
|
||||||
void *uhd_handler);
|
void *uhd_handler);
|
||||||
|
|
||||||
|
@ -90,8 +96,7 @@ SRSLTE_API void srslte_agc_lock(srslte_agc_t *q,
|
||||||
bool enable);
|
bool enable);
|
||||||
|
|
||||||
SRSLTE_API void srslte_agc_process(srslte_agc_t *q,
|
SRSLTE_API void srslte_agc_process(srslte_agc_t *q,
|
||||||
cf_t *input,
|
cf_t *signal,
|
||||||
cf_t *output,
|
|
||||||
uint32_t len);
|
uint32_t len);
|
||||||
|
|
||||||
#endif // AGC_
|
#endif // AGC_
|
||||||
|
|
|
@ -38,20 +38,31 @@
|
||||||
#include "srslte/utils/vector.h"
|
#include "srslte/utils/vector.h"
|
||||||
#include "srslte/utils/debug.h"
|
#include "srslte/utils/debug.h"
|
||||||
|
|
||||||
|
|
||||||
int srslte_agc_init (srslte_agc_t *q, srslte_agc_mode_t mode) {
|
int srslte_agc_init (srslte_agc_t *q, srslte_agc_mode_t mode) {
|
||||||
|
return srslte_agc_init_acc(q, mode, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_agc_init_acc(srslte_agc_t *q, srslte_agc_mode_t mode, uint32_t nof_frames) {
|
||||||
bzero(q, sizeof(srslte_agc_t));
|
bzero(q, sizeof(srslte_agc_t));
|
||||||
q->mode = mode;
|
q->mode = mode;
|
||||||
|
q->nof_frames = nof_frames;
|
||||||
|
if (nof_frames > 0) {
|
||||||
|
q->y_tmp = srslte_vec_malloc(sizeof(float) * nof_frames);
|
||||||
|
if (!q->y_tmp) {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
q->y_tmp = NULL;
|
||||||
|
}
|
||||||
q->target = SRSLTE_AGC_DEFAULT_TARGET;
|
q->target = SRSLTE_AGC_DEFAULT_TARGET;
|
||||||
srslte_agc_reset(q);
|
srslte_agc_reset(q);
|
||||||
return SRSLTE_SUCCESS;
|
return SRSLTE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srslte_agc_init_uhd(srslte_agc_t *q, srslte_agc_mode_t mode, double (set_gain_callback)(void*, double), void *uhd_handler) {
|
int srslte_agc_init_uhd(srslte_agc_t *q, srslte_agc_mode_t mode, uint32_t nof_frames, double (set_gain_callback)(void*, double), void *uhd_handler) {
|
||||||
if (!srslte_agc_init(q, mode)) {
|
if (!srslte_agc_init_acc(q, mode, nof_frames)) {
|
||||||
q->set_gain_callback = set_gain_callback;
|
q->set_gain_callback = set_gain_callback;
|
||||||
q->uhd_handler = uhd_handler;
|
q->uhd_handler = uhd_handler;
|
||||||
set_gain_callback(uhd_handler, 30.0);
|
|
||||||
return SRSLTE_SUCCESS;
|
return SRSLTE_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
|
@ -59,15 +70,21 @@ int srslte_agc_init_uhd(srslte_agc_t *q, srslte_agc_mode_t mode, double (set_gai
|
||||||
}
|
}
|
||||||
|
|
||||||
void srslte_agc_free(srslte_agc_t *q) {
|
void srslte_agc_free(srslte_agc_t *q) {
|
||||||
|
if (q->y_tmp) {
|
||||||
|
free(q->y_tmp);
|
||||||
|
}
|
||||||
bzero(q, sizeof(srslte_agc_t));
|
bzero(q, sizeof(srslte_agc_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void srslte_agc_reset(srslte_agc_t *q) {
|
void srslte_agc_reset(srslte_agc_t *q) {
|
||||||
q->bandwidth = SRSLTE_AGC_DEFAULT_BW;
|
q->bandwidth = SRSLTE_AGC_DEFAULT_BW;
|
||||||
q->lock = false;
|
q->lock = false;
|
||||||
q->gain = 1.0;
|
q->gain = pow(10,50/10);
|
||||||
q->y_out = 1.0;
|
q->y_out = 1.0;
|
||||||
q->isfirst = true;
|
q->isfirst = true;
|
||||||
|
if (q->set_gain_callback && q->uhd_handler) {
|
||||||
|
q->set_gain_callback(q->uhd_handler, 10*log10(q->gain));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void srslte_agc_set_bandwidth(srslte_agc_t *q, float bandwidth) {
|
void srslte_agc_set_bandwidth(srslte_agc_t *q, float bandwidth) {
|
||||||
|
@ -79,7 +96,7 @@ void srslte_agc_set_target(srslte_agc_t *q, float target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float srslte_agc_get_rssi(srslte_agc_t *q) {
|
float srslte_agc_get_rssi(srslte_agc_t *q) {
|
||||||
return 1.0/q->gain;
|
return q->target/q->gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
float srslte_agc_get_output_level(srslte_agc_t *q) {
|
float srslte_agc_get_output_level(srslte_agc_t *q) {
|
||||||
|
@ -94,56 +111,69 @@ void srslte_agc_lock(srslte_agc_t *q, bool enable) {
|
||||||
q->lock = enable;
|
q->lock = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void srslte_agc_process(srslte_agc_t *q, cf_t *input, cf_t *output, uint32_t len) {
|
void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) {
|
||||||
float gain_res = 1.0;
|
float gain_db = 10*log10(q->gain);
|
||||||
|
float gain_uhd_db = 1.0;
|
||||||
|
//float gain_uhd = 1.0;
|
||||||
|
float y = 0;
|
||||||
// Apply current gain to input signal
|
// Apply current gain to input signal
|
||||||
if (!q->uhd_handler) {
|
if (!q->uhd_handler) {
|
||||||
srslte_vec_sc_prod_cfc(input, q->gain, output, len);
|
srslte_vec_sc_prod_cfc(signal, q->gain, signal, len);
|
||||||
} else {
|
} else {
|
||||||
if (q->gain < 1) {
|
if (q->gain < 1) {
|
||||||
q->gain = 1.0;
|
q->gain = 1.0;
|
||||||
}
|
}
|
||||||
if (isinf(10*log10(q->gain)) || isnan(10*log10(q->gain))) {
|
if (isinf(gain_db) || isnan(gain_db)) {
|
||||||
q->gain = 1.0;
|
q->gain = 10.0;
|
||||||
}
|
} else {
|
||||||
gain_res = q->set_gain_callback(q->uhd_handler, 10*log10(q->gain));
|
gain_uhd_db = q->set_gain_callback(q->uhd_handler, gain_db);
|
||||||
gain_res = pow(10, gain_res/10);
|
//gain_uhd = pow(10, gain_uhd_db/10);
|
||||||
if (gain_res > q->gain) {
|
|
||||||
q->gain = gain_res;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float y = 0;
|
float *t;
|
||||||
switch(q->mode) {
|
switch(q->mode) {
|
||||||
case SRSLTE_AGC_MODE_ENERGY:
|
case SRSLTE_AGC_MODE_ENERGY:
|
||||||
y = sqrtf(crealf(srslte_vec_dot_prod_conj_ccc(output, output, len))/len);
|
y = sqrtf(crealf(srslte_vec_dot_prod_conj_ccc(signal, signal, len))/len);
|
||||||
break;
|
break;
|
||||||
case SRSLTE_AGC_MODE_PEAK_AMPLITUDE:
|
case SRSLTE_AGC_MODE_PEAK_AMPLITUDE:
|
||||||
y = -99;
|
t = (float*) signal;
|
||||||
for (int i=0;i<len;i++) {
|
y = t[srslte_vec_max_fi(t, 2*len)];// take only positive max to avoid abs() (should be similar)
|
||||||
if (fabs(crealf(input[i])) > y) {
|
|
||||||
y = fabs(crealf(input[i]));
|
|
||||||
}
|
|
||||||
if (fabs(cimagf(input[i])) > y) {
|
|
||||||
y = fabs(cimagf(input[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unsupported AGC mode\n");
|
fprintf(stderr, "Unsupported AGC mode\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float gg = 1.0;
|
if (q->nof_frames > 0) {
|
||||||
|
q->y_tmp[q->frame_cnt++] = y;
|
||||||
|
if (q->frame_cnt == q->nof_frames) {
|
||||||
|
q->frame_cnt = 0;
|
||||||
|
switch(q->mode) {
|
||||||
|
case SRSLTE_AGC_MODE_ENERGY:
|
||||||
|
y = srslte_vec_acc_ff(q->y_tmp, q->nof_frames)/q->nof_frames;
|
||||||
|
break;
|
||||||
|
case SRSLTE_AGC_MODE_PEAK_AMPLITUDE:
|
||||||
|
y = q->y_tmp[srslte_vec_max_fi(q->y_tmp, q->nof_frames)];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unsupported AGC mode\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double gg = 1.0;
|
||||||
if (q->isfirst) {
|
if (q->isfirst) {
|
||||||
q->y_out = y;
|
q->y_out = y;
|
||||||
q->gain = q->target/y;
|
|
||||||
q->isfirst = false;
|
q->isfirst = false;
|
||||||
} else {
|
} else {
|
||||||
q->y_out = (1-q->bandwidth) * q->y_out + q->bandwidth * y;
|
if (q->frame_cnt == 0) {
|
||||||
if (!q->lock) {
|
q->y_out = (1-q->bandwidth) * q->y_out + q->bandwidth * y;
|
||||||
gg = expf(-0.5*q->bandwidth*logf(q->y_out/q->target));
|
if (!q->lock) {
|
||||||
q->gain *= gg;
|
gg = expf(-0.5*q->bandwidth*logf(q->y_out/q->target));
|
||||||
}
|
q->gain *= gg;
|
||||||
|
}
|
||||||
|
INFO("AGC gain: %.2f (%.2f) y_out=%.3f, y=%.3f target=%.1f gg=%.2f %d/%d\n", gain_db, gain_uhd_db, q->y_out, y, q->target, gg, q->frame_cnt, q->nof_frames);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
INFO("AGC gain: %.3f (%.2f - %.2f) y_out=%.3f, y=%.3f target=%.1f gg=%.2f\n", q->gain, 10*log10(q->gain), gain_res, q->y_out, y, q->target, gg);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,11 +81,9 @@ clean_exit:
|
||||||
}
|
}
|
||||||
|
|
||||||
int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(void*, double)) {
|
int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(void*, double)) {
|
||||||
//int n = srslte_agc_init_uhd(&q->agc, SRSLTE_AGC_MODE_PEAK_AMPLITUDE, set_gain_callback, q->stream);
|
int n = srslte_agc_init_uhd(&q->agc, SRSLTE_AGC_MODE_PEAK_AMPLITUDE, 10, set_gain_callback, q->stream);
|
||||||
//q->do_agc = n==0?true:false;
|
q->do_agc = n==0?true:false;
|
||||||
//return n;
|
return n;
|
||||||
set_gain_callback(q->stream, 40);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int srslte_ue_sync_init(srslte_ue_sync_t *q,
|
int srslte_ue_sync_init(srslte_ue_sync_t *q,
|
||||||
|
@ -400,9 +398,6 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
|
||||||
fprintf(stderr, "Error receiving samples\n");
|
fprintf(stderr, "Error receiving samples\n");
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
if (q->do_agc) {
|
|
||||||
srslte_agc_process(&q->agc, q->input_buffer, q->input_buffer, q->sf_len);
|
|
||||||
}
|
|
||||||
switch (q->state) {
|
switch (q->state) {
|
||||||
case SF_FIND:
|
case SF_FIND:
|
||||||
ret = srslte_sync_find(&q->sfind, q->input_buffer, 0, &q->peak_idx);
|
ret = srslte_sync_find(&q->sfind, q->input_buffer, 0, &q->peak_idx);
|
||||||
|
@ -410,7 +405,10 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
|
||||||
fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
|
fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
if (q->do_agc) {
|
||||||
|
srslte_agc_process(&q->agc, q->input_buffer, q->sf_len);
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
ret = find_peak_ok(q);
|
ret = find_peak_ok(q);
|
||||||
}
|
}
|
||||||
|
@ -425,6 +423,10 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
|
||||||
/* Every SF idx 0 and 5, find peak around known position q->peak_idx */
|
/* Every SF idx 0 and 5, find peak around known position q->peak_idx */
|
||||||
if (q->sf_idx == 0 || q->sf_idx == 5) {
|
if (q->sf_idx == 0 || q->sf_idx == 5) {
|
||||||
|
|
||||||
|
if (q->do_agc) {
|
||||||
|
srslte_agc_process(&q->agc, q->input_buffer, q->sf_len);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MEASURE_EXEC_TIME
|
#ifdef MEASURE_EXEC_TIME
|
||||||
struct timeval t[3];
|
struct timeval t[3];
|
||||||
gettimeofday(&t[1], NULL);
|
gettimeofday(&t[1], NULL);
|
||||||
|
|
Loading…
Reference in New Issue