Correction in AWGN generator

master
Xavier Arteaga 5 years ago committed by Xavier Arteaga
parent ca9611654d
commit cd2f86687f

@ -41,7 +41,7 @@ extern "C" {
* The srsLTE channel AWGN implements an efficient Box-Muller Method accelerated with SIMD. * The srsLTE channel AWGN implements an efficient Box-Muller Method accelerated with SIMD.
*/ */
typedef struct { typedef struct {
cf_t* table_exp; float* table_cos;
float* table_log; float* table_log;
uint32_t rand_state; uint32_t rand_state;
float std_dev; float std_dev;

@ -59,9 +59,9 @@ int srslte_channel_awgn_init(srslte_channel_awgn_t* q, uint32_t seed)
q->rand_state = seed; q->rand_state = seed;
// Allocate complex exponential and logarithmic tables // Allocate complex exponential and logarithmic tables
q->table_exp = srslte_vec_cf_malloc(AWGN_TABLE_ALLOC_SIZE); q->table_cos = srslte_vec_f_malloc(AWGN_TABLE_ALLOC_SIZE);
q->table_log = srslte_vec_f_malloc(AWGN_TABLE_ALLOC_SIZE); q->table_log = srslte_vec_f_malloc(AWGN_TABLE_ALLOC_SIZE);
if (!q->table_exp || !q->table_log) { if (!q->table_cos || !q->table_log) {
ERROR("Malloc\n"); ERROR("Malloc\n");
} }
@ -70,7 +70,7 @@ int srslte_channel_awgn_init(srslte_channel_awgn_t* q, uint32_t seed)
float temp1 = (float)i / (float)AWGN_TABLE_SIZE; float temp1 = (float)i / (float)AWGN_TABLE_SIZE;
float temp2 = (float)(i + 1) / (float)AWGN_TABLE_SIZE; float temp2 = (float)(i + 1) / (float)AWGN_TABLE_SIZE;
q->table_exp[i] = cexpf(I * 2.0f * (float)M_PI * temp1); q->table_cos[i] = cosf(2.0f * (float)M_PI * temp1);
q->table_log[i] = sqrtf(-2.0f * logf(temp2)); q->table_log[i] = sqrtf(-2.0f * logf(temp2));
} }
@ -88,15 +88,15 @@ int srslte_channel_awgn_init(srslte_channel_awgn_t* q, uint32_t seed)
do { do {
idx = channel_awgn_rand(q) % AWGN_TABLE_SIZE; idx = channel_awgn_rand(q) % AWGN_TABLE_SIZE;
} while (idx == i); } while (idx == i);
cf_t temp_exp = q->table_exp[i]; float temp_cos = q->table_cos[i];
q->table_exp[i] = q->table_exp[idx]; q->table_cos[i] = q->table_cos[idx];
q->table_exp[idx] = temp_exp; q->table_cos[idx] = temp_cos;
} }
// Copy head in tail for keeping continuity in SIMD registers // Copy head in tail for keeping continuity in SIMD registers
for (uint32_t i = 0; i < SRSLTE_SIMD_F_SIZE; i++) { for (uint32_t i = 0; i < SRSLTE_SIMD_F_SIZE; i++) {
q->table_log[i + AWGN_TABLE_SIZE] = q->table_log[i]; q->table_log[i + AWGN_TABLE_SIZE] = q->table_log[i];
q->table_exp[i + AWGN_TABLE_SIZE] = q->table_exp[i]; q->table_cos[i + AWGN_TABLE_SIZE] = q->table_cos[i];
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
@ -124,7 +124,7 @@ static inline void channel_awgn_run(srslte_channel_awgn_t* q, const float* in, f
#if SRSLTE_SIMD_F_SIZE #if SRSLTE_SIMD_F_SIZE
for (; i < (int)size - SRSLTE_SIMD_F_SIZE + 1; i += SRSLTE_SIMD_F_SIZE) { for (; i < (int)size - SRSLTE_SIMD_F_SIZE + 1; i += SRSLTE_SIMD_F_SIZE) {
// Load SIMD registers // Load SIMD registers
simd_f_t t1 = srslte_simd_f_loadu((float*)&q->table_exp[channel_awgn_rand(q)]); simd_f_t t1 = srslte_simd_f_loadu(&q->table_cos[channel_awgn_rand(q)]);
simd_f_t t2 = srslte_simd_f_loadu(&q->table_log[channel_awgn_rand(q)]); simd_f_t t2 = srslte_simd_f_loadu(&q->table_log[channel_awgn_rand(q)]);
simd_f_t in_ = srslte_simd_f_loadu(&in[i]); simd_f_t in_ = srslte_simd_f_loadu(&in[i]);
simd_f_t out_ = srslte_simd_f_set1(std_dev); simd_f_t out_ = srslte_simd_f_set1(std_dev);
@ -153,23 +153,16 @@ static inline void channel_awgn_run(srslte_channel_awgn_t* q, const float* in, f
float n = std_dev; float n = std_dev;
n *= q->table_log[idx1]; n *= q->table_log[idx1];
n *= q->table_cos[idx2];
cf_t t_exp = q->table_exp[idx2]; out[i] = in[i] + n;
float n1 = n * __real__ t_exp;
float n2 = n * __imag__ t_exp;
out[i] = in[i] + n1;
i++;
if (i < size) {
out[i] = in[i] + n2;
}
} }
} }
void srslte_channel_awgn_run_c(srslte_channel_awgn_t* q, const cf_t* in, cf_t* out, uint32_t size) void srslte_channel_awgn_run_c(srslte_channel_awgn_t* q, const cf_t* in, cf_t* out, uint32_t size)
{ {
channel_awgn_run(q, (float*)in, (float*)out, 2 * size, q->std_dev * (float)M_SQRT1_2); channel_awgn_run(q, (float*)in, (float*)out, 2 * size, q->std_dev * (float)M_SQRT1_2);
// srslte_ch_awgn_c(in, out, q->std_dev * M_SQRT1_2, size);
} }
void srslte_channel_awgn_run_f(srslte_channel_awgn_t* q, const float* in, float* out, uint32_t size) void srslte_channel_awgn_run_f(srslte_channel_awgn_t* q, const float* in, float* out, uint32_t size)
@ -183,8 +176,8 @@ void srslte_channel_awgn_free(srslte_channel_awgn_t* q)
return; return;
} }
if (q->table_exp) { if (q->table_cos) {
free(q->table_exp); free(q->table_cos);
} }
if (q->table_log) { if (q->table_log) {

@ -101,13 +101,18 @@ int main(int argc, char** argv)
#ifdef ENABLE_GUI #ifdef ENABLE_GUI
sdrgui_init(); sdrgui_init();
sdrgui_init_title("SRS Fading channel"); sdrgui_init_title("SRS AWGN Channel");
plot_real_t plot_fft = NULL; plot_real_t plot_fft = NULL;
plot_scatter_t plot_scatter = NULL;
plot_real_init(&plot_fft); plot_real_init(&plot_fft);
plot_real_setTitle(&plot_fft, "AWGN"); plot_real_setTitle(&plot_fft, "Spectrum");
plot_real_addToWindowGrid(&plot_fft, (char*)"Spectrum", 0, 0); plot_real_addToWindowGrid(&plot_fft, (char*)"Spectrum", 0, 0);
plot_scatter_init(&plot_scatter);
plot_scatter_setTitle(&plot_fft, "IQ");
plot_scatter_addToWindowGrid(&plot_fft, (char*)"IQ", 1, 0);
cf_t* fft_out = srslte_vec_cf_malloc(nof_samples); cf_t* fft_out = srslte_vec_cf_malloc(nof_samples);
srslte_dft_plan_t fft = {}; srslte_dft_plan_t fft = {};
if (srslte_dft_plan_c(&fft, nof_samples, SRSLTE_DFT_FORWARD)) { if (srslte_dft_plan_c(&fft, nof_samples, SRSLTE_DFT_FORWARD)) {
@ -142,6 +147,8 @@ int main(int argc, char** argv)
} }
#ifdef ENABLE_GUI #ifdef ENABLE_GUI
plot_scatter_setNewData(&plot_scatter, output_buffer, nof_samples);
srslte_dft_run_c(&fft, output_buffer, fft_out); srslte_dft_run_c(&fft, output_buffer, fft_out);
float min = +INFINITY; float min = +INFINITY;

Loading…
Cancel
Save