Added AGC

master
ismagom 10 years ago
parent ad9d02927e
commit 5e5c7b27d4

@ -58,6 +58,8 @@ SRSLTE_API double cuhd_set_rx_srate(void *h,
SRSLTE_API double cuhd_set_rx_gain(void *h,
double gain);
SRSLTE_API double cuhd_get_rx_gain(void *h);
SRSLTE_API double cuhd_set_rx_freq(void *h,
double freq);

@ -164,6 +164,12 @@ double cuhd_set_rx_gain(void *h, double gain)
return handler->usrp->get_rx_gain();
}
double cuhd_get_rx_gain(void *h)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
return handler->usrp->get_rx_gain();
}
double cuhd_set_rx_freq(void *h, double freq)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);

@ -60,6 +60,8 @@ int cuhd_mib_decoder(void *uhd, uint32_t max_nof_frames, srslte_cell_t *cell) {
goto clean_exit;
}
srslte_ue_sync_start_agc(&ue_mib.ue_sync, cuhd_set_rx_gain);
int srate = srslte_sampling_freq_hz(SRSLTE_UE_MIB_NOF_PRB);
INFO("Setting sampling frequency %.2f MHz for PSS search\n", (float) srate/1000000);
cuhd_set_rx_srate(uhd, (float) srate);
@ -107,6 +109,8 @@ int cuhd_cell_search(void *uhd, cell_search_cfg_t *config,
if (config->threshold) {
srslte_ue_cellsearch_set_threshold(&cs, config->threshold);
}
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/1000000);
cuhd_set_rx_srate(uhd, SRSLTE_CS_SAMP_FREQ);

@ -369,6 +369,8 @@ int main(int argc, char **argv) {
bool decode_pdsch;
int pdcch_tx=0;
srslte_ue_sync_start_agc(&ue_sync, cuhd_set_rx_gain);
INFO("\nEntering main loop...\n\n", 0);
/* Main loop */
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
@ -377,7 +379,7 @@ int main(int argc, char **argv) {
if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
}
/* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
if (ret == 1) {
switch (state) {
@ -458,7 +460,16 @@ int main(int argc, char **argv) {
if (srslte_ue_sync_get_sfidx(&ue_sync) != 5 && srslte_ue_sync_get_sfidx(&ue_sync) != 0) {
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
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
@ -468,13 +479,15 @@ int main(int argc, char **argv) {
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total,ue_dl.pkt_errors);
#else
printf("CFO: %+6.2f KHz, SFO: %+6.2f Khz, "
"RSRP: %+5.1f dBm, RSRQ: %5.1f dB, SNR: %4.1f dB, "
"PDCCH-Miss: %5.2f%% (%u), PDSCH-BLER: %5.2f%% (%u)\r",
"RSRP: %+5.1f dBm, SNR: %4.1f dB, "
"PDCCH-Miss: %5.2f%% (%u), PDSCH-BLER: %5.2f%% Peak: %.2f Gain: %.1f dB/%.1f\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000,
10*log10(rsrp*1000)-gain_offset,
10*log10(rsrq), 10*log10(snr),
10*log10(snr),
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, ue_dl.pkt_errors);
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total, max, cuhd_get_rx_gain(uhd),
10*log10(ue_sync.agc.gain)
);
#endif
}

@ -43,24 +43,42 @@
#include "srslte/config.h"
#define SRSLTE_AGC_DEFAULT_BW (5e-2)
#define SRSLTE_AGC_DEFAULT_TARGET 0.5
#define SRSLTE_AGC_DEFAULT_BW (5e-1)
typedef enum SRSLTE_API {
SRSLTE_AGC_MODE_ENERGY = 0,
SRSLTE_AGC_MODE_PEAK_AMPLITUDE
} srslte_agc_mode_t;
typedef struct SRSLTE_API{
float bandwidth;
float gain;
double gain;
float y_out;
bool lock;
bool isfirst;
void *uhd_handler;
double (*set_gain_callback) (void*,double);
srslte_agc_mode_t mode;
float target;
} srslte_agc_t;
SRSLTE_API int srslte_agc_init (srslte_agc_t *q);
SRSLTE_API int srslte_agc_init(srslte_agc_t *q, srslte_agc_mode_t mode);
SRSLTE_API int srslte_agc_init_uhd(srslte_agc_t *q,
srslte_agc_mode_t mode,
double (set_gain_callback)(void*, double),
void *uhd_handler);
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_bandwidth(srslte_agc_t *q,
float bandwidth);
float bandwidth);
SRSLTE_API void srslte_agc_set_target(srslte_agc_t *q,
float target);
SRSLTE_API float srslte_agc_get_rssi(srslte_agc_t *q);

@ -55,6 +55,7 @@
#include "srslte/config.h"
#include "srslte/sync/sync.h"
#include "srslte/sync/cfo.h"
#include "srslte/agc/agc.h"
#include "srslte/ch_estimation/chest_dl.h"
#include "srslte/phch/pbch.h"
#include "srslte/dft/ofdm.h"
@ -69,7 +70,10 @@ typedef enum SRSLTE_API { SF_FIND, SF_TRACK} srslte_ue_sync_state_t;
typedef struct SRSLTE_API {
srslte_sync_t sfind;
srslte_sync_t strack;
srslte_agc_t agc;
bool do_agc;
void *stream;
int (*recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*);
srslte_timestamp_t last_timestamp;
@ -123,6 +127,9 @@ SRSLTE_API int srslte_ue_sync_init_file(srslte_ue_sync_t *q,
SRSLTE_API void srslte_ue_sync_free(srslte_ue_sync_t *q);
SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q,
double (set_gain_callback)(void*, double));
SRSLTE_API uint32_t srslte_ue_sync_sf_len(srslte_ue_sync_t *q);
SRSLTE_API int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q,

@ -39,12 +39,25 @@
#include "srslte/utils/debug.h"
int srslte_agc_init (srslte_agc_t *q) {
int srslte_agc_init (srslte_agc_t *q, srslte_agc_mode_t mode) {
bzero(q, sizeof(srslte_agc_t));
q->mode = mode;
q->target = SRSLTE_AGC_DEFAULT_TARGET;
srslte_agc_reset(q);
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) {
if (!srslte_agc_init(q, mode)) {
q->set_gain_callback = set_gain_callback;
q->uhd_handler = uhd_handler;
set_gain_callback(uhd_handler, 30.0);
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR;
}
}
void srslte_agc_free(srslte_agc_t *q) {
bzero(q, sizeof(srslte_agc_t));
}
@ -61,6 +74,10 @@ void srslte_agc_set_bandwidth(srslte_agc_t *q, float bandwidth) {
q->bandwidth = bandwidth;
}
void srslte_agc_set_target(srslte_agc_t *q, float target) {
q->target = target;
}
float srslte_agc_get_rssi(srslte_agc_t *q) {
return 1.0/q->gain;
}
@ -73,28 +90,60 @@ float srslte_agc_get_gain(srslte_agc_t *q) {
return q->gain;
}
void srslte_agc_lock(srslte_agc_t *q, bool enable) {
q->lock = enable;
}
void srslte_agc_process(srslte_agc_t *q, cf_t *input, cf_t *output, uint32_t len) {
float gain_res = 1.0;
// Apply current gain to input signal
srslte_vec_sc_prod_cfc(input, q->gain, output, len);
// compute output energy estimate
float y = sqrtf(crealf(srslte_vec_dot_prod_conj_ccc(output, output, len))/len);
if (!q->uhd_handler) {
srslte_vec_sc_prod_cfc(input, q->gain, output, len);
} else {
if (q->gain < 1) {
q->gain = 1.0;
}
if (isinf(10*log10(q->gain)) || isnan(10*log10(q->gain))) {
q->gain = 1.0;
}
gain_res = q->set_gain_callback(q->uhd_handler, 10*log10(q->gain));
gain_res = pow(10, gain_res/10);
if (gain_res > q->gain) {
q->gain = gain_res;
}
}
float y = 0;
switch(q->mode) {
case SRSLTE_AGC_MODE_ENERGY:
y = sqrtf(crealf(srslte_vec_dot_prod_conj_ccc(output, output, len))/len);
break;
case SRSLTE_AGC_MODE_PEAK_AMPLITUDE:
y = -99;
for (int i=0;i<len;i++) {
if (fabs(crealf(input[i])) > y) {
y = fabs(crealf(input[i]));
}
if (fabs(cimagf(input[i])) > y) {
y = fabs(cimagf(input[i]));
}
}
break;
default:
fprintf(stderr, "Unsupported AGC mode\n");
return;
}
float gg = 1.0;
if (q->isfirst) {
q->y_out = y;
q->gain = 1/y;
q->gain = q->target/y;
q->isfirst = false;
} else {
q->y_out = (1-q->bandwidth) * q->y_out + q->bandwidth * y;
if (!q->lock) {
q->gain *= expf(-0.5*q->bandwidth*logf(q->y_out));
gg = expf(-0.5*q->bandwidth*logf(q->y_out/q->target));
q->gain *= gg;
}
}
DEBUG("AGC gain: %.3f y_out=%.3f, y=%.3f\n", q->gain, q->y_out, y);
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);
}

@ -57,7 +57,7 @@ int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_n
bzero(q, sizeof(srslte_ue_sync_t));
q->file_mode = true;
q->sf_len = SRSLTE_SF_LEN(srslte_symbol_sz(nof_prb));
if (srslte_filesource_init(&q->file_source, file_name, SRSLTE_COMPLEX_FLOAT_BIN)) {
fprintf(stderr, "Error opening file %s\n", file_name);
goto clean_exit;
@ -80,6 +80,12 @@ clean_exit:
return ret;
}
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);
q->do_agc = n==0?true:false;
return n;
}
int srslte_ue_sync_init(srslte_ue_sync_t *q,
srslte_cell_t cell,
int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*),
@ -193,6 +199,9 @@ void srslte_ue_sync_free(srslte_ue_sync_t *q) {
if (q->input_buffer) {
free(q->input_buffer);
}
if (q->do_agc) {
srslte_agc_free(&q->agc);
}
if (!q->file_mode) {
srslte_sync_free(&q->sfind);
srslte_sync_free(&q->strack);
@ -390,7 +399,9 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
fprintf(stderr, "Error receiving samples\n");
return SRSLTE_ERROR;
}
if (q->do_agc) {
srslte_agc_process(&q->agc, q->input_buffer, q->input_buffer, q->sf_len);
}
switch (q->state) {
case SF_FIND:
ret = srslte_sync_find(&q->sfind, q->input_buffer, 0, &q->peak_idx);

Loading…
Cancel
Save