Commit 5449a37b authored by Elena Lukashova's avatar Elena Lukashova

Adding changes related to whitening filter.

MRC core function to be further optimized in the future commits.
At this point some configurations could fail.
parent 38925d35
......@@ -46,7 +46,7 @@
#include "linear_preprocessing_rec.h"
#define NOCYGWIN_STATIC
//#define DEBUG_MMSE
//#define DEBUG_FRONT_END
/* dynamic shift for LLR computation for TM3/4
......@@ -1782,6 +1782,7 @@ void dlsch_channel_compensation_core(int **rxdataF_ext,
length2 = length>>3;
for (ii=0; ii<length2; ++ii) {
if (mod_order>2) {
// get channel amplitude if not QPSK
......@@ -3366,7 +3367,6 @@ void dlsch_dual_stream_correlation_core(int **dl_ch_estimates_ext,
{
#if defined(__x86_64__)||defined(__i386__)
unsigned short rb;
__m128i *dl_ch128,*dl_ch128i,*dl_ch_rho128,mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3;
unsigned char aarx;
int ii, length2, length_mod8;
......@@ -3601,8 +3601,11 @@ void dlsch_detection_mrc_core(int **rxdataF_comp,
unsigned char aatx;
int i;
__m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1,
*dl_ch_mag128_i0,*dl_ch_mag128_i1,*dl_ch_mag128_i0b,*dl_ch_mag128_i1b;
__m128i *rxdataF_comp128_0, *rxdataF_comp128_1, *rxdataF_comp128_2, *rxdataF_comp128_3;
__m128i *dl_ch_mag128_0, *dl_ch_mag128_1, *dl_ch_mag128_2, *dl_ch_mag128_3;
__m128i *dl_ch_mag128_0b, *dl_ch_mag128_1b, *dl_ch_mag128_2b, *dl_ch_mag128_3b;
__m128i *rho128_0, *rho128_1, *rho128_2, *rho128_3;
__m128i *rho128_i0, *rho128_i1, *rho128_i2, *rho128_i3;
int length_mod4 = 0;
int length2;
......@@ -3628,16 +3631,19 @@ void dlsch_detection_mrc_core(int **rxdataF_comp,
}
}
if (rho) {
rho128_0 = (__m128i *) &rho[0][start_point];
rho128_1 = (__m128i *) &rho[1][start_point];
rho128_2 = (__m128i *) &rho[2][start_point];
rho128_3 = (__m128i *) &rho[3][start_point];
if (length_mod4 == 0){
length2 = length>>2;
for (i=0; i<length2; ++i) {
rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_1[i],1));
rho128_2[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_2[i],1),_mm_srai_epi16(rho128_3[i],1));
}
}
}
......@@ -3645,14 +3651,63 @@ void dlsch_detection_mrc_core(int **rxdataF_comp,
if (rho_i){
rho128_i0 = (__m128i *) &rho_i[0][start_point];
rho128_i1 = (__m128i *) &rho_i[1][start_point];
rho128_i2 = (__m128i *) &rho_i[2][start_point];
rho128_i3 = (__m128i *) &rho_i[3][start_point];
if (length_mod4 == 0){
length2 = length>>2;
for (i=0; i<length2; ++i)
rho128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_i0[i],1),_mm_srai_epi16(rho128_i1[i],1));
rho128_i2[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_i2[i],1),_mm_srai_epi16(rho128_i3[i],1));
}
}
if (n_tx == 4){
rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[0][start_point];
rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[2][start_point];
rxdataF_comp128_2 = (__m128i *)&rxdataF_comp[4][start_point];
rxdataF_comp128_3 = (__m128i *)&rxdataF_comp[6][start_point];
dl_ch_mag128_0 = (__m128i *)&dl_ch_mag[0][start_point];
dl_ch_mag128_1 = (__m128i *)&dl_ch_mag[2][start_point];
dl_ch_mag128_2 = (__m128i *)&dl_ch_mag[4][start_point];
dl_ch_mag128_3 = (__m128i *)&dl_ch_mag[6][start_point];
dl_ch_mag128_0b = (__m128i *)&dl_ch_magb[0][start_point];
dl_ch_mag128_1b = (__m128i *)&dl_ch_magb[2][start_point];
dl_ch_mag128_2b = (__m128i *)&dl_ch_magb[4][start_point];
dl_ch_mag128_3b = (__m128i *)&dl_ch_magb[6][start_point];
rho128_0 = (__m128i *)&rho[0][start_point];
rho128_1 = (__m128i *)&rho[2][start_point];
rho128_i0 = (__m128i *)&rho_i[0][start_point];
rho128_i1 = (__m128i *)&rho_i[2][start_point];
if (length_mod4 == 0){
length2 = length>>2;
for (i=0; i<length2; ++i) {
rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1));
rxdataF_comp128_2[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_2[i],1),_mm_srai_epi16(rxdataF_comp128_3[i],1));
dl_ch_mag128_0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0[i],1),_mm_srai_epi16(dl_ch_mag128_1[i],1));
dl_ch_mag128_2[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_2[i],1),_mm_srai_epi16(dl_ch_mag128_3[i],1));
dl_ch_mag128_0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0b[i],1),_mm_srai_epi16(dl_ch_mag128_1b[i],1));
dl_ch_mag128_2b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_2b[i],1),_mm_srai_epi16(dl_ch_mag128_3b[i],1));
rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_1[i],1));
rho128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_i0[i],1),_mm_srai_epi16(rho128_i1[i],1));
}
}
}
}
_mm_empty();
......@@ -3662,7 +3717,7 @@ void dlsch_detection_mrc_core(int **rxdataF_comp,
unsigned char aatx;
int i;
int16x8_t *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1,*dl_ch_mag128_i0,*dl_ch_mag128_i1,*dl_ch_mag128_i0b,*dl_ch_mag128_i1b;
int16x8_t *rxdataF_comp128_0,*rxdataF_comp128_1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1;
int length_mod4 = 0;
int length2;
int ii=0;
......@@ -4174,14 +4229,12 @@ void dlsch_channel_level_median(int **dl_ch_estimates_ext,
short ii;
int aatx,aarx;
int length_mod4;
int length_mod8;
int length2;
int max = 0, min=0;
int norm_pack;
__m128i *dl_ch128, norm128D;
int16_t x = factor2(length);
int16_t y = (length)>>x;
for (aatx=0; aatx<n_tx; aatx++){
for (aarx=0; aarx<n_rx; aarx++) {
......@@ -4191,14 +4244,15 @@ void dlsch_channel_level_median(int **dl_ch_estimates_ext,
dl_ch128=(__m128i *)&dl_ch_estimates_ext[aatx*2 + aarx][start_point];
length_mod4=length&3;
length_mod8=length&3;
if (length_mod8 == 0){
length2 = length>>2;
for (ii=0;ii<length2;ii++) {
norm128D = _mm_srai_epi32( _mm_madd_epi16(dl_ch128[0],dl_ch128[0]), 1);
//print_ints("norm128D",&norm128D[0]);
norm_pack = ((int32_t*)&norm128D)[0] +
((int32_t*)&norm128D)[1] +
((int32_t*)&norm128D)[2] +
......@@ -4208,12 +4262,13 @@ void dlsch_channel_level_median(int **dl_ch_estimates_ext,
max = norm_pack;
if (norm_pack < min)
min = norm_pack;
dl_ch128+=1;
}
median[aatx*n_rx + aarx] = (max+min)>>1;
}else {
printf ("channel_level_median: Received number of subcarriers is not multiple of 8, \n"
"need to adapt the code!\n");
}
// printf("Channel level median [%d]: %d\n",aatx*n_rx + aarx, median[aatx*n_rx + aarx]);
}
}
......@@ -4224,12 +4279,14 @@ void dlsch_channel_level_median(int **dl_ch_estimates_ext,
#elif defined(__arm__)
short rb;
unsigned char aatx,aarx,nre=12,symbol_mod;
unsigned char aatx,aarx;
int length_mod8;
int length2;
int32x4_t norm128D;
int16x4_t *dl_ch128;
for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++){
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
for (aatx=0; aatx<n_tx; aatx++){
for (aarx=0; aarx<n_rx; aarx++) {
max = 0;
min = 0;
norm128D = vdupq_n_s32(0);
......@@ -4237,6 +4294,8 @@ void dlsch_channel_level_median(int **dl_ch_estimates_ext,
dl_ch128=(int16x4_t *)&dl_ch_estimates_ext[aatx*n_rx + aarx][start_point];
length_mod8=length&3;
if (length_mod8 == 0){
length2 = length>>2;
for (ii=0;ii<length2;ii++) {
......@@ -4255,6 +4314,10 @@ void dlsch_channel_level_median(int **dl_ch_estimates_ext,
}
median[aatx*n_rx + aarx] = (max+min)>>1;
}else {
printf ("channel_level_median: Received number of subcarriers is not multiple of 8, \n"
"need to adapt the code!\n");
}
//printf("Channel level median [%d]: %d\n",aatx*n_rx + aarx, median[aatx*n_rx + aarx]);
}
......@@ -4346,26 +4409,36 @@ void mmse_processing_core(int32_t **rxdataF_ext,
float real;
float complex **W_MMSE= malloc(n_tx*n_rx*sizeof(float complex*));
float complex **W_MMSE = malloc(n_tx*n_rx*sizeof(float complex*));
for (int j=0; j<n_tx*n_rx; j++) {
W_MMSE[j] = malloc(sizeof(float complex)*length);
}
float complex *H= malloc(n_tx*n_rx*sizeof(float complex));
float complex *H = malloc(n_tx*n_rx*sizeof(float complex));
float complex *W_MMSE_re= malloc(n_tx*n_rx*sizeof(float complex));
float complex** dl_ch_estimates_ext_flcpx = malloc(n_tx*n_rx*sizeof(float complex*));
float complex** dl_ch_estimates_ext_flp = malloc(n_tx*n_rx*sizeof(float complex*));
for (int j=0; j<n_tx*n_rx; j++) {
dl_ch_estimates_ext_flp[j] = malloc(sizeof(float complex)*length);
}
float complex** dl_ch_estimates_ext_eff_flp = malloc(n_tx*n_rx*sizeof(float complex*));
for (int j=0; j<n_tx*n_rx; j++) {
dl_ch_estimates_ext_flcpx[j] = malloc(sizeof(float complex)*length);
dl_ch_estimates_ext_eff_flp[j] = malloc(sizeof(float complex)*length);
}
float complex** rxdataF_ext_flcpx = malloc(n_rx*sizeof(float complex*));
float complex** rxdataF_ext_flp = malloc(n_rx*sizeof(float complex*));
for (int j=0; j<n_rx; j++) {
rxdataF_ext_flcpx[j] = malloc(sizeof(float complex)*length);
rxdataF_ext_flp[j] = malloc(sizeof(float complex)*length);
}
float complex** rxdataF_ext_mmse_flp = malloc(n_rx*sizeof(float complex*));
for (int j=0; j<n_rx; j++) {
rxdataF_ext_mmse_flp[j] = malloc(sizeof(float complex)*length);
}
chan_est_to_float(dl_ch_estimates_ext,
dl_ch_estimates_ext_flcpx,
dl_ch_estimates_ext_flp,
n_tx,
n_rx,
length,
......@@ -4374,8 +4447,8 @@ void mmse_processing_core(int32_t **rxdataF_ext,
for (re=0; re<length; re++){
for (aatx=0; aatx<n_tx; aatx++){
for (aarx=0; aarx<n_rx; aarx++) {
imag = cimag(dl_ch_estimates_ext_flcpx[aatx*n_rx + aarx][re]);
real = creal(dl_ch_estimates_ext_flcpx[aatx*n_rx + aarx][re]);
imag = cimag(dl_ch_estimates_ext_flp[aatx*n_rx + aarx][re]);
real = creal(dl_ch_estimates_ext_flp[aatx*n_rx + aarx][re]);
H[aatx*n_rx + aarx] = real+ I*imag;
}
}
......@@ -4388,37 +4461,40 @@ void mmse_processing_core(int32_t **rxdataF_ext,
}
rxdataF_to_float(rxdataF_ext,
rxdataF_ext_flcpx,
rxdataF_ext_flp,
n_rx,
length,
start_point);
mult_mmse_rxdataF(W_MMSE,
rxdataF_ext_flcpx,
mult_filter_rxdataF(W_MMSE,
rxdataF_ext_flp,
rxdataF_ext_mmse_flp,
n_tx,
n_rx,
length,
start_point);
mult_mmse_chan_est(W_MMSE,
dl_ch_estimates_ext_flcpx,
mult_filter_chan_est(W_MMSE,
dl_ch_estimates_ext_flp,
dl_ch_estimates_ext_eff_flp,
n_tx,
n_rx,
n_tx,
length,
start_point);
float_to_rxdataF(rxdataF_ext,
rxdataF_ext_flcpx,
float_to_rxdataF(rxdataF_ext_mmse_flp,
rxdataF_ext,
n_tx,
n_rx,
length,
start_point);
float_to_chan_est(dl_ch_estimates_ext,
dl_ch_estimates_ext_flcpx,
float_to_chan_est(dl_ch_estimates_ext_eff_flp,
dl_ch_estimates_ext,
n_tx,
n_rx,
length,
......@@ -4427,48 +4503,253 @@ void mmse_processing_core(int32_t **rxdataF_ext,
free(W_MMSE);
free(H);
free(W_MMSE_re);
free(dl_ch_estimates_ext_flcpx);
free(rxdataF_ext_flcpx);
free(dl_ch_estimates_ext_flp);
free(dl_ch_estimates_ext_eff_flp);
free(rxdataF_ext_flp);
free(rxdataF_ext_mmse_flp);
}
/*THIS FUNCTION TAKES FLOAT_POINT INPUT. SHOULD NOT BE USED WITH OAI*/
void mmse_processing_core_flp(float complex** rxdataF_ext_flcpx,
float complex **H,
int32_t **rxdataF_ext,
int32_t **dl_ch_estimates_ext,
float noise_power,
int n_tx,
int n_rx,
int length,
int start_point){
void whitening_processing_core_flp(float complex **rxdataF_flp,
float complex **chan_est_flp_0,
float complex **chan_est_flp_1,
int32_t **rxdataF_filt_fp_0,
int32_t **rxdataF_filt_fp_1,
int32_t **chan_est_eff_fp_0,
int32_t **chan_est_eff_fp_1,
float sigma2,
uint8_t n_tx,
uint8_t n_rx,
int32_t length,
int32_t start_point)
{
uint8_t aatx, aarx;
float max_0 = 0.0;
float max_1 = 0.0;
float one_over_max_0 = 0.0;
float one_over_max_1 = 0.0;
int32_t i, re;
float complex *W_Wh_0_vec, *W_Wh_1_vec;
float complex *rxdataF_filt_flp_0_vec, *rxdataF_filt_flp_1_vec;
float complex *chan_est_eff_flp_0_vec, *chan_est_eff_flp_1_vec;
float complex *W_Wh_0[n_tx*n_rx], *W_Wh_1[n_tx*n_rx];
float complex *rxdataF_filt_flp_0[n_rx], *rxdataF_filt_flp_1[n_rx];
float complex *chan_est_eff_flp_0[n_rx*(n_tx>>1)], *chan_est_eff_flp_1[n_rx*(n_tx>>1)];
float complex *W_Wh_0_re, *W_Wh_1_re;
float complex *chan_est_flp_re_0, *chan_est_flp_re_1;
int aatx, aarx, re;
float max = 0;
float one_over_max = 0;
W_Wh_0_vec = (float complex*)calloc(n_tx*n_rx*length, sizeof(float complex*));
W_Wh_1_vec = (float complex*)calloc(n_tx*n_rx*length, sizeof(float complex*));
float complex **W_MMSE= malloc(n_tx*n_rx*sizeof(float complex*));
for (int j=0; j<n_tx*n_rx; j++) {
W_MMSE[j] = malloc(sizeof(float complex)*length);
for (i = 0; i < n_tx*n_rx; ++i) {
W_Wh_0[i] = &W_Wh_0_vec[i*length];
W_Wh_1[i] = &W_Wh_1_vec[i*length];
}
float complex *H_re= malloc(n_tx*n_rx*sizeof(float complex));
float complex *W_MMSE_re= malloc(n_tx*n_rx*sizeof(float complex));
rxdataF_filt_flp_0_vec = (float complex*)calloc(n_rx*length,sizeof(float complex*));
rxdataF_filt_flp_1_vec = (float complex*)calloc(n_rx*length,sizeof(float complex*));
for (i = 0; i < n_rx; ++i) {
// Received signal after W_wh on branch 0 and branch 1
rxdataF_filt_flp_0[i] = &rxdataF_filt_flp_0_vec[i*length];
rxdataF_filt_flp_1[i] = &rxdataF_filt_flp_1_vec[i*length];
}
chan_est_eff_flp_0_vec = (float complex*)calloc(n_rx*(n_tx>>1)*length, sizeof(float complex*));
chan_est_eff_flp_1_vec = (float complex*)calloc(n_rx*(n_tx>>1)*length, sizeof(float complex*));
for (i = 0; i < n_rx*(n_tx>>1); ++i) {
// Received signal after W_wh on branch 0 and branch 1
chan_est_eff_flp_0[i] = &chan_est_eff_flp_0_vec[i*length];
chan_est_eff_flp_1[i] = &chan_est_eff_flp_1_vec[i*length];
}
W_Wh_0_re = (float complex*)calloc(n_tx*n_rx, sizeof(float complex));
W_Wh_1_re = (float complex*)calloc(n_tx*n_rx, sizeof(float complex));
chan_est_flp_re_0 = (float complex*)calloc(n_rx*(n_tx>>1), sizeof(float complex));
chan_est_flp_re_1 = (float complex*)calloc(n_rx*(n_tx>>1), sizeof(float complex));
for (re = 0; re < length; ++re){
for (aatx = 0; aatx < n_tx/2; ++aatx){
for (aarx = 0; aarx < n_rx; ++aarx) {
chan_est_flp_re_0[aatx*n_rx + aarx] = chan_est_flp_0[aatx*n_rx + aarx][re];
chan_est_flp_re_1[aatx*n_rx + aarx] = chan_est_flp_1[aatx*n_rx + aarx][re];
}
}
compute_white_filter(chan_est_flp_re_0, chan_est_flp_re_1, sigma2, n_tx, n_rx, W_Wh_0_re, W_Wh_1_re);
for (aatx = 0; aatx < n_tx; ++aatx){
for (aarx = 0; aarx < n_rx; ++aarx) {
W_Wh_0[aatx*n_rx + aarx][re] = W_Wh_0_re[aatx*n_rx + aarx];
W_Wh_1[aatx*n_rx + aarx][re] = W_Wh_1_re[aatx*n_rx + aarx];
if (fabs(creal(W_Wh_0_re[aatx*n_rx + aarx])) > max_0)
max_0 = fabs(creal(W_Wh_0_re[aatx*n_rx + aarx]));
if (fabs(cimag(W_Wh_0_re[aatx*n_rx + aarx])) > max_0)
max_0 = fabs(cimag(W_Wh_0_re[aatx*n_rx + aarx]));
if (fabs(creal(W_Wh_1_re[aatx*n_rx + aarx])) > max_1)
max_1 = fabs(creal(W_Wh_1_re[aatx*n_rx + aarx]));
if (fabs(cimag(W_Wh_1_re[aatx*n_rx + aarx])) > max_1)
max_1 = fabs(cimag(W_Wh_1_re[aatx*n_rx + aarx]));
}
}
}
// Not convinced normalization is needed.
#if 0
one_over_max_0 = 1.0;///max_0;
one_over_max_1 = 1.0;//max_1;
for (re=0; re<length; re++){
for (aatx=0; aatx<n_tx; aatx++){
for (aarx=0; aarx<n_rx; aarx++) {
H_re[aatx*n_rx + aarx] = H[aatx*n_rx + aarx][re];
#ifdef DEBUG_MMSE
for (aarx=0; aarx<n_rx; aarx++){
#ifdef DEBUG_FRONT_END
if (re == 0){
printf("whitening_processing_core_flp: W_Wh_0[%d] = (%f + i%f)\n", aatx*n_rx + aarx, creal(W_Wh_0[aatx*n_rx + aarx][re]), cimag(W_Wh_0[aatx*n_rx + aarx][re]));
printf("whitening_processing_core_flp: W_Wh_1[%d] = (%f + i%f)\n", aatx*n_rx + aarx, creal(W_Wh_1[aatx*n_rx + aarx][re]), cimag(W_Wh_1[aatx*n_rx + aarx][re]));
}
#endif
W_Wh_0[aatx*n_rx + aarx][re] = one_over_max_0*W_Wh_0[aatx*n_rx + aarx][re];
W_Wh_1[aatx*n_rx + aarx][re] = one_over_max_1*W_Wh_1[aatx*n_rx + aarx][re];
#ifdef DEBUG_FRONT_END
if (re == 0)
printf(" H_re[%d]= (%f + i%f)\n", aatx*n_rx + aarx, creal(H_re[aatx*n_rx + aarx]), cimag(H_re[aatx*n_rx + aarx]));
printf("whitening_processing_core_flp: AFTER NORM W_Wh_0[%d] = (%f + i%f), max_0 = %f \n", aatx*n_rx + aarx, creal(W_Wh_0[aatx*n_rx + aarx][re]), cimag(W_Wh_0[aatx*n_rx + aarx][re]), max_0);
printf("whitening_processing_core_flp: AFTER NORM W_Wh_1[%d] = (%f + i%f), max_1 = %f \n", aatx*n_rx + aarx, creal(W_Wh_1[aatx*n_rx + aarx][re]), cimag(W_Wh_1[aatx*n_rx + aarx][re]), max_1);
#endif
}
}
compute_MMSE(H_re, n_tx, noise_power, W_MMSE_re);
for (aatx=0; aatx<n_tx; aatx++){
for (aarx=0; aarx<n_rx; aarx++) {
}
#endif
// Branch 0
mult_filter_rxdataF(W_Wh_0,
rxdataF_flp,
rxdataF_filt_flp_0,
n_tx,
n_rx,
length,
start_point);
mult_filter_chan_est(W_Wh_0,
chan_est_flp_0,
chan_est_eff_flp_0,
n_tx,
n_rx,
(n_tx>>1),
length,
start_point);
float_to_rxdataF(rxdataF_filt_flp_0,
rxdataF_filt_fp_0,
n_tx,
n_rx,
length,
start_point);
float_to_chan_est(chan_est_eff_flp_0,
chan_est_eff_fp_0,
(n_tx>>1),
n_rx,
length,
start_point);
// Branch 1
mult_filter_rxdataF(W_Wh_1,
rxdataF_flp,
rxdataF_filt_flp_1,
n_tx,
n_rx,
length,
start_point);
mult_filter_chan_est(W_Wh_1,
chan_est_flp_1,
chan_est_eff_flp_1,
n_tx,
n_rx,
(n_tx>>1),
length,
start_point);
float_to_rxdataF(rxdataF_filt_flp_1,
rxdataF_filt_fp_1,
n_tx,
n_rx,
length,
start_point);
float_to_chan_est(chan_est_eff_flp_1,
chan_est_eff_fp_1,
(n_tx>>1),
n_rx,
length,
start_point);
free(W_Wh_0_vec);
free(W_Wh_1_vec);
free(rxdataF_filt_flp_0_vec);
free(rxdataF_filt_flp_1_vec);
free(chan_est_eff_flp_0_vec);
free(chan_est_eff_flp_1_vec);
free(W_Wh_0_re);
free(W_Wh_1_re);
free(chan_est_flp_re_0);
free(chan_est_flp_re_1);
}
/*THIS FUNCTION TAKES FLOAT_POINT INPUT. SHOULD NOT BE USED WITH OAI*/
void mmse_processing_core_flp(float complex** rxdataF_flp,
float complex **chan_est_flp,
int32_t **rxdataF_filt_fp,
int32_t **chan_est_eff_fp,
float noise_power,
uint8_t n_tx,
uint8_t n_rx,
int32_t length,
int32_t start_point){
uint8_t aatx, aarx;
float max = 0;
float one_over_max = 0;
int32_t i, re;
float complex *W_MMSE_vec, *rxdataF_filt_flp_vec, *chan_est_eff_flp_vec;
float complex *W_MMSE[n_tx*n_rx], *rxdataF_filt_flp[n_rx], *chan_est_eff_flp[n_tx*n_rx];
W_MMSE_vec = (float complex*)calloc(n_tx*n_rx*length, sizeof(float complex*));
for (i = 0; i < n_tx*n_rx; ++i) {
W_MMSE[i] = &W_MMSE_vec[i*length];
}
rxdataF_filt_flp_vec = (float complex*)calloc(n_rx*length, sizeof(float complex*));
for (i = 0; i < n_rx; ++i) {
rxdataF_filt_flp[i] = &rxdataF_filt_flp_vec[i*length];
}
chan_est_eff_flp_vec = (float complex*)calloc(n_tx*n_rx*length, sizeof(float complex*));
for (i = 0; i < n_tx*n_rx; ++i) {
chan_est_eff_flp[i] = &chan_est_eff_flp_vec[i*length];
}
float complex *chan_est_flp_re = calloc(n_tx*n_rx, sizeof(float complex));
float complex *W_MMSE_re = calloc(n_tx*n_rx, sizeof(float complex));
for (re = 0; re < length; ++re){
for (aatx = 0; aatx < n_tx; ++aatx){
for (aarx = 0; aarx < n_rx; ++aarx) {
chan_est_flp_re[aatx*n_rx + aarx] = chan_est_flp[aatx*n_rx + aarx][re];
}
}
compute_MMSE(chan_est_flp_re, n_tx, noise_power, W_MMSE_re);
for (aatx = 0; aatx < n_tx; ++aatx){
for (aarx = 0; aarx < n_rx; ++aarx) {
W_MMSE[aatx*n_rx + aarx][re] = W_MMSE_re[aatx*n_rx + aarx];
if (fabs(creal(W_MMSE_re[aatx*n_rx + aarx])) > max)
max = fabs(creal(W_MMSE_re[aatx*n_rx + aarx]));
......@@ -4477,54 +4758,67 @@ void mmse_processing_core_flp(float complex** rxdataF_ext_flcpx,
}
}
}
one_over_max = 1.0/max;
for (re=0; re<length; re++)
for (aatx=0; aatx<n_tx; aatx++)
for (aarx=0; aarx<n_rx; aarx++){
#ifdef DEBUG_MMSE
if (re == 0)
printf(" W_MMSE[%d] = (%f + i%f)\n", aatx*n_rx + aarx, creal(W_MMSE[aatx*n_rx + aarx][re]), cimag(W_MMSE[aatx*n_rx + aarx][re]));
for (re = 0; re < length; ++re){
for (aatx = 0; aatx < n_tx; ++aatx){
for (aarx = 0; aarx < n_rx; ++aarx){
#ifdef DEBUG_FRONT_END
if (re == 0){
printf("mmse_processing_core_flp: W_MMSE[%d] = (%f + i%f)\n", aatx*n_rx + aarx, creal(W_MMSE[aatx*n_rx + aarx][re]), cimag(W_MMSE[aatx*n_rx + aarx][re]));
}
#endif
W_MMSE[aatx*n_rx + aarx][re] = one_over_max*W_MMSE[aatx*n_rx + aarx][re];
#ifdef DEBUG_MMSE
if (re == 0)
printf(" AFTER NORM W_MMSE[%d] = (%f + i%f), max = %f \n", aatx*n_rx + aarx, creal(W_MMSE[aatx*n_rx + aarx][re]), cimag(W_MMSE[aatx*n_rx + aarx][re]), max);
#endif
#ifdef DEBUG_FRONT_END
if (re == 0){
printf("mmse_processing_core_flp: AFTER NORM W_MMSE[%d] = (%f + i%f), max = %f \n", aatx*n_rx + aarx, creal(W_MMSE[aatx*n_rx + aarx][re]), cimag(W_MMSE[aatx*n_rx + aarx][re]), max);
}
#endif
}
}
}
mult_mmse_rxdataF(W_MMSE,
rxdataF_ext_flcpx,
mult_filter_rxdataF(W_MMSE,
rxdataF_flp,
rxdataF_filt_flp,
n_tx,
n_rx,
length,
start_point);
mult_mmse_chan_est(W_MMSE,
H,
mult_filter_chan_est(W_MMSE,
chan_est_flp,
chan_est_eff_flp,
n_tx,
n_rx,
n_tx,
length,
start_point);
float_to_rxdataF(rxdataF_ext,
rxdataF_ext_flcpx,
float_to_rxdataF(rxdataF_filt_flp,
rxdataF_filt_fp,
n_tx,
n_rx,
length,
start_point);
float_to_chan_est(dl_ch_estimates_ext,
H,
float_to_chan_est(chan_est_eff_flp,
chan_est_eff_fp,
n_tx,
n_rx,
length,
start_point);
free(H_re);
free(W_MMSE);
free(W_MMSE_re);
free(W_MMSE_vec);
free(W_MMSE_re);
free(rxdataF_filt_flp_vec);
free(chan_est_eff_flp_vec);
free(chan_est_flp_re);
}
......@@ -4636,7 +4930,7 @@ void rxdataF_to_float(int32_t **rxdataF_ext,
imag = (int16_t) (rxdataF_ext[aarx][start_point + re] >> 16);
real = (int16_t) (rxdataF_ext[aarx][start_point + re] & 0xffff);
rxdataF_f[aarx][re] = (float)(real/(32768.0)) + I*(float)(imag/(32768.0));
#ifdef DEBUG_MMSE
#ifdef DEBUG_FRONT_END
if (re==0){
printf("rxdataF_to_float: aarx = %d, real= %d, imag = %d\n", aarx, real, imag);
//printf("rxdataF_to_float: rxdataF_ext[%d][%d] = %d\n", aarx, start_point + re, rxdataF_ext[aarx][start_point + re]);
......@@ -4651,26 +4945,26 @@ void rxdataF_to_float(int32_t **rxdataF_ext,
void chan_est_to_float(int32_t **dl_ch_estimates_ext,
float complex **dl_ch_estimates_ext_f,
int n_tx,
int n_rx,
int length,
int start_point)
uint8_t n_tx,
uint8_t n_rx,
int32_t length,
int32_t start_point)
{
short re;
int aatx,aarx;
int32_t re;
uint8_t aatx,aarx;
int16_t imag;
int16_t real;
for (aatx=0; aatx<n_tx; aatx++){
for (aarx=0; aarx<n_rx; aarx++) {
for (re=0; re<length; re++){
for (aatx = 0; aatx < n_tx; ++aatx){
for (aarx = 0; aarx < n_rx; ++aarx) {
for (re = 0; re < length; ++re){
imag = (int16_t) (dl_ch_estimates_ext[aatx*n_rx + aarx][start_point + re] >> 16);
real = (int16_t) (dl_ch_estimates_ext[aatx*n_rx + aarx][start_point+ re] & 0xffff);
dl_ch_estimates_ext_f[aatx*n_rx + aarx][re] = (float)(real/(32768.0)) + I*(float)(imag/(32768.0));
#ifdef DEBUG_MMSE
if (re==0){
printf("ant %d, re = %d, real = %d, imag = %d \n", aatx*n_rx + aarx, re, real, imag);
printf("ant %d, re = %d, real = %f, imag = %f \n", aatx*n_rx + aarx, re, creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]), cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]));
#ifdef DEBUG_FRONT_END
if (re == 0){
printf("chan_est_to_float: ant %d, re = %d, real = %d, imag = %d \n", aatx*n_rx + aarx, re, real, imag);
printf("chan_est_to_float: ant %d, re = %d, real = %f, imag = %f \n", aatx*n_rx + aarx, re, creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]), cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]));
}
#endif
}
......@@ -4678,82 +4972,84 @@ void chan_est_to_float(int32_t **dl_ch_estimates_ext,
}
}
void float_to_chan_est(int32_t **dl_ch_estimates_ext,
float complex **dl_ch_estimates_ext_f,
void float_to_chan_est(float complex **chan_est_flp,
int32_t **result,
int n_tx,
int n_rx,
int length,
int start_point)
{
short re;
int aarx, aatx;
int16_t imag;
int16_t real;
for (aatx=0; aatx<n_tx; aatx++){
for (aarx=0; aarx<n_rx; aarx++) {
for (re=0; re<length; re++){
if (cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])<-1)
for (aatx = 0; aatx < n_tx; ++aatx){
for (aarx = 0; aarx < n_rx; ++aarx) {
for (re = 0; re < length; ++re){
if (cimag(chan_est_flp[aatx*n_rx + aarx][re]) < -1)
imag = 0x8000;
else if (cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])>=1)
else if (cimag(chan_est_flp[aatx*n_rx + aarx][re]) >= 1)
imag = 0x7FFF;
else
imag = cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])*32768;
if (creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])<-1)
imag = cimag(chan_est_flp[aatx*n_rx + aarx][re]) * 32768;
if (creal(chan_est_flp[aatx*n_rx + aarx][re]) < -1)
real = 0x8000;
else if (creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])>=1)
else if (creal(chan_est_flp[aatx*n_rx + aarx][re]) >= 1)
real = 0x7FFF;
else
real = creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])*32768;
real = creal(chan_est_flp[aatx*n_rx + aarx][re]) * 32768;
dl_ch_estimates_ext[aatx*n_rx + aarx][start_point + re] = (((int32_t)imag)<<16)|((int32_t)real & 0xffff);
#ifdef DEBUG_MMSE
if (re==0){
printf(" float_to_chan_est: chan est real = %f, chan est imag = %f\n",creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]), cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]));
result[aatx*n_rx + aarx][start_point + re] = (((int32_t)imag)<<16)|((int32_t)real & 0xffff);
#ifdef DEBUG_FRONT_END
if (re == 0){
printf(" float_to_chan_est: chan est real = %f, chan est imag = %f\n",creal(chan_est_flp[aatx*n_rx + aarx][re]), cimag(chan_est_flp[aatx*n_rx + aarx][re]));
printf("float_to_chan_est: real fixed = %d, imag fixed = %d\n", real, imag);
printf("float_to_chan_est: ant %d, re = %d, dl_ch_estimates_ext = %d \n", aatx*n_rx + aarx, re, dl_ch_estimates_ext[aatx*n_rx + aarx][start_point + re]);
printf("float_to_chan_est: ant %d, re = %d, result = %d \n", aatx*n_rx + aarx, re, result[aatx*n_rx + aarx][start_point + re]);
}
#endif
}
}
}
}
void float_to_rxdataF(int32_t **rxdataF_ext,
float complex **rxdataF_f,
int n_tx,
int n_rx,
int length,
int start_point)
void float_to_rxdataF(float complex **rxdataF_flp,
int32_t **result,
uint8_t n_tx,
uint8_t n_rx,
int32_t length,
int32_t start_point)
{
short re;
int aarx;
int32_t re;
uint8_t aarx;
int16_t imag;
int16_t real;
for (aarx=0; aarx<n_rx; aarx++) {
for (re=0; re<length; re++){
if (cimag(rxdataF_f[aarx][re])<-1)
for (aarx = 0; aarx < n_rx; ++aarx) {
for (re = 0; re < length; ++re){
if (cimag(rxdataF_flp[aarx][re]) < -1)
imag = 0x8000;
else if (cimag(rxdataF_f[aarx][re])>=1)
else if (cimag(rxdataF_flp[aarx][re]) >= 1)
imag = 0x7FFF;
else
imag = cimag(rxdataF_f[aarx][re])*32768;
if (creal(rxdataF_f[aarx][re])<-1)
imag = cimag(rxdataF_flp[aarx][re]) * 32768;
if (creal(rxdataF_flp[aarx][re]) < -1)
real = 0x8000;
else if (creal(rxdataF_f[aarx][re])>=1)
else if (creal(rxdataF_flp[aarx][re]) >= 1)
real = 0x7FFF;
else
real = creal(rxdataF_f[aarx][re])*32768;
rxdataF_ext[aarx][start_point + re] = (((int32_t)imag)<<16)|(((int32_t)real) & 0xffff);
#ifdef DEBUG_MMSE
if (re==0){
printf(" float_to_rxdataF: real = %f, imag = %f\n",creal(rxdataF_f[aarx][re]), cimag(rxdataF_f[aarx][re]));
real = creal(rxdataF_flp[aarx][re]) * 32768;
result[aarx][start_point + re] = (((int32_t)imag)<<16)|(((int32_t)real) & 0xffff);
#ifdef DEBUG_FRONT_END
if (re == 0){
printf(" float_to_rxdataF: real = %f, imag = %f\n",creal(rxdataF_flp[aarx][re]), cimag(rxdataF_flp[aarx][re]));
printf("float_to_rxdataF: real fixed = %d, imag fixed = %d\n", real, imag);
printf("float_to_rxdataF: ant %d, re = %d, rxdataF_ext = %d \n", aarx, re, rxdataF_ext[aarx][start_point + re]);
printf("float_to_rxdataF: ant %d, re = %d, result = %d \n", aarx, re, result[aarx][start_point + re]);
}
#endif
}
......@@ -4761,95 +5057,110 @@ void float_to_rxdataF(int32_t **rxdataF_ext,
}
void mult_mmse_rxdataF(float complex** Wmmse,
float complex** rxdataF_ext_f,
int n_tx,
int n_rx,
int length,
int start_point)
void mult_filter_rxdataF(float complex **W,
float complex **rxdataF_flp,
float complex **result,
uint8_t n_tx,
uint8_t n_rx,
int32_t length,
int32_t start_point)
{
short re;
int aarx, aatx;
int32_t re;
uint8_t aarx, aatx;
float complex *rxdata_re = malloc(n_rx*sizeof(float complex));
float complex *result_re = malloc(n_rx*sizeof(float complex));
float complex *W_re = malloc(n_tx*n_rx*sizeof(float complex));
float complex* rxdata_re = malloc(n_rx*sizeof(float complex));
float complex* rxdata_mmse_re = malloc(n_rx*sizeof(float complex));
float complex* Wmmse_re = malloc(n_tx*n_rx*sizeof(float complex));
for (re = 0;re < length; ++re){
for (aarx = 0; aarx < n_rx; ++aarx){
rxdata_re[aarx] = rxdataF_flp[aarx][re];
for (re=0;re<length; re++){
for (aarx=0; aarx<n_rx; aarx++){
rxdata_re[aarx] = rxdataF_ext_f[aarx][re];
#ifdef DEBUG_MMSE
if (re==0)
printf("mult_mmse_rxdataF before: rxdata_re[%d] = (%f, %f)\n", aarx, creal(rxdata_re[aarx]), cimag(rxdata_re[aarx]));
#ifdef DEBUG_FRONT_END
if (re == 0)
printf("mult_filter_rxdataF before: rxdata_re[%d] = (%f, %f)\n", aarx, creal(rxdata_re[aarx]), cimag(rxdata_re[aarx]));
#endif
}
for (aatx=0; aatx<n_tx; aatx++){
for (aarx=0; aarx<n_rx; aarx++){
Wmmse_re[aatx*n_rx + aarx] = Wmmse[aatx*n_rx + aarx][re];
for (aatx = 0; aatx < n_tx; ++aatx){
for (aarx = 0; aarx < n_rx; ++aarx){
W_re[aatx*n_rx + aarx] = W[aatx*n_rx + aarx][re];
}
}
mutl_matrix_matrix_col_based(Wmmse_re, rxdata_re, n_rx, n_tx, n_rx, 1, rxdata_mmse_re);
for (aarx=0; aarx<n_rx; aarx++){
rxdataF_ext_f[aarx][re] = rxdata_mmse_re[aarx];
#ifdef DEBUG_MMSE
if (re==0)
printf("mult_mmse_rxdataF after: rxdataF_ext_f[%d] = (%f, %f)\n", aarx, creal(rxdataF_ext_f[aarx][re]), cimag(rxdataF_ext_f[aarx][re]));
mutl_matrix_matrix_col_based(W_re, rxdata_re, n_rx, n_tx, n_rx, 1, result_re);
for (aarx = 0; aarx < n_rx; ++aarx){
result[aarx][re] = result_re[aarx];
#ifdef DEBUG_FRONT_END
if (re == 0)
printf("mult_filter_rxdataF after: result[%d] = (%f, %f)\n", aarx, creal(result[aarx][re]), cimag(result[aarx][re]));
#endif
}
}
free(rxdata_re);
free(rxdata_mmse_re);
free(Wmmse_re);
free(result_re);
free(W_re);
}
void mult_mmse_chan_est(float complex** Wmmse,
float complex** dl_ch_estimates_ext_f,
int n_tx,
int n_rx,
int length,
int start_point)
void mult_filter_chan_est(float complex **W,
float complex **chan_est_flp,
float complex **result,
uint8_t n_tx,
uint8_t n_rx,
int32_t n_col_chan_est_flp,
int32_t length,
int32_t start_point)
{
short re;
int aarx, aatx;
int32_t re;
uint8_t aarx, aatx;
float complex* chan_est_re = malloc(n_tx*n_rx*sizeof(float complex));
float complex* chan_est_mmse_re = malloc(n_tx*n_rx*sizeof(float complex));
float complex* Wmmse_re = malloc(n_tx*n_rx*sizeof(float complex));
float complex* chan_est_re = malloc(n_col_chan_est_flp*n_rx*sizeof(float complex));
float complex* result_re = malloc(n_col_chan_est_flp*n_rx*sizeof(float complex));
float complex* W_re = malloc(n_tx*n_rx*sizeof(float complex));
for (re=0;re<length; re++){
for (aatx=0; aatx<n_tx; aatx++){
for (aarx=0; aarx<n_rx; aarx++){
chan_est_re[aatx*n_rx + aarx] = dl_ch_estimates_ext_f[aatx*n_rx + aarx][re];
Wmmse_re[aatx*n_rx + aarx] = Wmmse[aatx*n_rx + aarx][re];
#ifdef DEBUG_MMSE
for (re = 0;re < length; ++re){
for (aatx = 0; aatx < n_tx; ++aatx){
for (aarx = 0; aarx < n_rx; ++aarx){
W_re[aatx*n_rx + aarx] = W[aatx*n_rx + aarx][re];
}
}
for (aatx = 0; aatx < n_col_chan_est_flp; ++aatx){
for (aarx = 0; aarx < n_rx; ++aarx){
chan_est_re[aatx*n_rx + aarx] = chan_est_flp[aatx*n_rx + aarx][re];
#ifdef DEBUG_FRONT_END
if (re==0)
printf("mult_mmse_chan_est: chan_est_re[%d] = (%f, %f)\n", aatx*n_rx + aarx, creal(chan_est_re[aatx*n_rx + aarx]), cimag(chan_est_re[aatx*n_rx + aarx]));
printf("mult_filter_chan_est: chan_est_re[%d] = (%f, %f)\n", aatx*n_rx + aarx, creal(chan_est_re[aatx*n_rx + aarx]), cimag(chan_est_re[aatx*n_rx + aarx]));
#endif
}
}
mutl_matrix_matrix_col_based(Wmmse_re, chan_est_re, n_rx, n_tx, n_rx, n_tx, chan_est_mmse_re);
for (aatx=0; aatx<n_tx; aatx++){
for (aarx=0; aarx<n_rx; aarx++){
dl_ch_estimates_ext_f[aatx*n_rx + aarx][re] = chan_est_mmse_re[aatx*n_rx + aarx];
#ifdef DEBUG_MMSE
if (re==0)
printf("mult_mmse_chan_est: dl_ch_estimates_ext_f[%d][%d] = (%f, %f)\n", aatx*n_rx + aarx, re, creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]), cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]));
mutl_matrix_matrix_col_based(W_re, chan_est_re, n_rx, n_tx, n_rx, n_col_chan_est_flp, result_re);
for (aatx = 0; aatx < n_col_chan_est_flp; ++aatx){
for (aarx = 0; aarx < n_rx; ++aarx){
result[aatx*n_rx + aarx][re] = result_re[aatx*n_rx + aarx];
#ifdef DEBUG_FRONT_END
if (re==0){
printf("mult_filter_chan_est: result[%d][%d] = (%f, %f)\n", aatx*n_rx + aarx, re, creal(result[aatx*n_rx + aarx][re]), cimag(result[aatx*n_rx + aarx][re]));
}
#endif
}
}
}
free(Wmmse_re);
free(W_re);
free(chan_est_re);
free(chan_est_mmse_re);
free(result_re);
}
//compute average channel_level of effective (precoded) channel
void dlsch_channel_level_TM34(int **dl_ch_estimates_ext,
LTE_DL_FRAME_PARMS *frame_parms,
......
......@@ -59,42 +59,26 @@ void transpose (int N, float complex *A, float complex *Result)
}
void conjugate_transpose (int N, float complex *A, float complex *Result)
void conjugate_transpose (int rows_A, int col_A, float complex *A, float complex *Result)
{
// Computes C := alpha*op(A)*op(B) + beta*C,
enum CBLAS_TRANSPOSE transa = CblasConjTrans;
enum CBLAS_TRANSPOSE transb = CblasNoTrans;
int rows_opA = N; // number of rows in op(A) and in C
int col_opB = N; //number of columns of op(B) and in C
int col_opA = N; //number of columns in op(A) and rows in op(B)
int col_B; //number of columns in B
float complex alpha = 1.0+I*0;
int lda = rows_opA;
float complex beta = 0.0+I*0;
int ldc = rows_opA;
float complex alpha = 1.0;
float complex beta = 0.0;
int i;
float complex* B;
int ldb = col_opB;
if (transb == CblasNoTrans) {
B = (float complex*)calloc(ldb*col_opB,sizeof(float complex));
col_B= col_opB;
}
else {
B = (float complex*)calloc(ldb*col_opA, sizeof(float complex));
col_B = col_opA;
}
float complex* C = (float complex*)malloc(ldc*col_opB*sizeof(float complex));
B = (float complex*)calloc(rows_A*rows_A,sizeof(float complex));
for (i=0; i<lda*col_B; i+=N+1)
B[i]=1.0+I*0;
cblas_cgemm(CblasRowMajor, transa, transb, rows_opA, col_opB, col_opA, &alpha, A, lda, B, ldb, &beta, C, ldc);
for (i=0; i<rows_A*rows_A; i+=rows_A+1)
B[i]=1.0;
memcpy(Result, C, N*N*sizeof(float complex));
cblas_cgemm(CblasColMajor, transa, transb, col_A, rows_A, rows_A, &alpha, A, rows_A, B, rows_A, &beta, Result, col_A);
free(B);
free(C);
}
void H_hermH_plus_sigma2I (int N, int M, float complex *A, float sigma2, float complex *Result)
......@@ -124,27 +108,20 @@ void H_hermH_plus_sigma2I (int N, int M, float complex *A, float sigma2, float c
}
void HH_herm_plus_sigma2I (int M, int N, float complex *A, float sigma2, float complex *Result)
void HH_herm_plus_sigma2I (int rows_A, int col_A, float complex *A, float sigma2, float complex *Result)
{
//C := alpha*op(A)*op(B) + beta*C,
enum CBLAS_TRANSPOSE transa = CblasNoTrans;
enum CBLAS_TRANSPOSE transb = CblasConjTrans;
int k = N; //number of columns in op(A) and rows in op(B),k
float complex alpha = 1.0+I*0;
int lda = N;
int ldb = N;
int ldc = M;
int i;
float complex* C = (float complex*)calloc(M*M, sizeof(float complex));
for (i = 0; i < rows_A*rows_A; i += rows_A+1)
Result[i]=1.0+I*0;
for (i=0; i<M*M; i+=M+1)
C[i]=1.0+I*0;
cblas_cgemm(CblasRowMajor, transa, transb, M, M, k, &alpha, A, lda, A, ldb, &sigma2, C, ldc);
memcpy(Result, C, M*M*sizeof(float complex));
free(C);
cblas_cgemm(CblasColMajor, transa, transb, rows_A, rows_A, col_A, &alpha, A, rows_A, A, rows_A, &sigma2, Result, rows_A);
}
......@@ -153,14 +130,14 @@ void eigen_vectors_values (int N, float complex *A, float complex *Vectors, floa
// This function computes ORTHONORMAL eigenvectors and eigenvalues of matrix A,
// where Values_Matrix is a diagonal matrix of eigenvalues.
// A=Vectors*Values_Matrix*Vectors'
char jobz = 'V';
char jobz = 'V'; // compute both eigenvectors and eigenvalues
char uplo = 'U';
int order_A = N;
int lda = N;
int i;
float* Values = (float*)malloc(sizeof(float)*1*N);
float* Values = (float*)calloc(1*N, sizeof(float));
LAPACKE_cheev(LAPACK_ROW_MAJOR, jobz, uplo, order_A, A, lda, Values);
LAPACKE_cheev(LAPACK_COL_MAJOR, jobz, uplo, order_A, A, lda, Values);
memcpy(Vectors, A, N*N*sizeof(float complex));
......@@ -178,7 +155,7 @@ void eigen_vectors_values (int N, float complex *A, float complex *Vectors, floa
int nrhs = N;
char transa = 'N';
int* IPIV = malloc(N*N*sizeof(int));
int* IPIV = calloc(N*N, sizeof(int));
// Compute LU-factorization
LAPACKE_cgetrf(LAPACK_ROW_MAJOR, n, nrhs, A, lda, IPIV);
......@@ -208,23 +185,24 @@ void mutl_matrix_matrix_row_based(float complex* M0, float complex* M1, int rows
#ifdef DEBUG_PREPROC
int i=0;
printf("rows_M0 %d, col_M0 %d, rows_M1 %d, col_M1 %d\n", rows_M0, col_M0, rows_M1, col_M1);
printf("mutl_matrix_matrix_row_based: rows_M0 %d, col_M0 %d, rows_M1 %d, col_M1 %d\n", rows_M0, col_M0, rows_M1, col_M1);
for(i=0; i<rows_M0*col_M0; ++i)
printf(" rows_opA = %d, col_opB = %d, W_MMSE[%d] = (%f + i%f)\n", rows_opA, col_opB, i , creal(M0[i]), cimag(M0[i]));
printf("mutl_matrix_matrix_row_based: rows_opA = %d, col_opB = %d, W_MMSE[%d] = (%f + i%f)\n", rows_opA, col_opB, i , creal(M0[i]), cimag(M0[i]));
for(i=0; i<rows_M1*col_M1; ++i)
printf(" M1[%d] = (%f + i%f)\n", i , creal(M1[i]), cimag(M1[i]));
printf("mutl_matrix_matrix_row_based: M1[%d] = (%f + i%f)\n", i , creal(M1[i]), cimag(M1[i]));
#endif
cblas_cgemm(CblasRowMajor, transa, transb, rows_opA, col_opB, col_opA, &alpha, M0, lda, M1, ldb, &beta, Result, ldc);
#ifdef DEBUG_PREPROC
for(i=0; i<rows_opA*col_opB; ++i)
printf(" result[%d] = (%f + i%f)\n", i , creal(Result[i]), cimag(Result[i]));
printf("mutl_matrix_matrix_row_based: result[%d] = (%f + i%f)\n", i , creal(Result[i]), cimag(Result[i]));
#endif
}
void mutl_matrix_matrix_col_based(float complex* M0, float complex* M1, int rows_M0, int col_M0, int rows_M1, int col_M1, float complex* Result ){
enum CBLAS_TRANSPOSE transa = CblasNoTrans;
enum CBLAS_TRANSPOSE transb = CblasNoTrans;
......@@ -239,21 +217,56 @@ void mutl_matrix_matrix_col_based(float complex* M0, float complex* M1, int rows
#ifdef DEBUG_PREPROC
int i = 0;
printf("rows_M0 %d, col_M0 %d, rows_M1 %d, col_M1 %d\n", rows_M0, col_M0, rows_M1, col_M1);
for(i=0; i<rows_M0*col_M0; ++i)
printf(" rows_opA = %d, col_opB = %d, W_MMSE[%d] = (%f + i%f)\n", rows_opA, col_opB, i , creal(M0[i]), cimag(M0[i]));
printf("mutl_matrix_matrix_col_based: rows_M0 %d, col_M0 %d, rows_M1 %d, col_M1 %d\n", rows_M0, col_M0, rows_M1, col_M1);
for(i = 0; i < rows_M0*col_M0; ++i)
printf("mutl_matrix_matrix_col_based: rows_opA = %d, col_opB = %d, filter[%d] = (%f + i%f)\n", rows_opA, col_opB, i , creal(M0[i]), cimag(M0[i]));
for(i=0; i<rows_M1*col_M1; ++i)
printf(" M1[%d] = (%f + i%f)\n", i , creal(M1[i]), cimag(M1[i]));
for(i = 0; i < rows_M1*col_M1; ++i)
printf("mutl_matrix_matrix_col_based: M1[%d] = (%f + i%f)\n", i , creal(M1[i]), cimag(M1[i]));
#endif
cblas_cgemm(CblasColMajor, transa, transb, rows_opA, col_opB, col_opA, &alpha, M0, lda, M1, ldb, &beta, Result, ldc);
#ifdef DEBUG_PREPROC
for(i=0; i<rows_opA*col_opB; ++i)
printf(" result[%d] = (%f + i%f)\n", i , creal(Result[i]), cimag(Result[i]));
for(i = 0; i < rows_opA*col_opB; ++i)
printf("mutl_matrix_matrix_col_based: result[%d] = (%f + i%f)\n", i , creal(Result[i]), cimag(Result[i]));
#endif
}
void mutl_scal_matrix_matrix_col_based(float *M0, float complex *M1, float alpha, int rows_M0, int col_M0, int rows_M1, int col_M1, float complex *Result ){
enum CBLAS_TRANSPOSE transa = CblasNoTrans;
enum CBLAS_TRANSPOSE transb = CblasNoTrans;
float complex beta = 0.0;
int i;
float complex *D_0_complex = calloc(rows_M0*col_M0, sizeof(float complex));
for(i = 0; i < rows_M0*col_M0; ++i){
D_0_complex[i] = M0[i] + I*0.00001;
#ifdef DEBUG_PREPROC
printf("mutl_scal_matrix_matrix_col_based: D_0_complex[%d] = (%f, %f)\n", i , creal(D_0_complex[i]), cimag(D_0_complex[i]));
#endif
}
#ifdef DEBUG_PREPROC
printf("mutl_scal_matrix_matrix_col_based: alpha = %f\n", alpha);
for(i = 0; i < rows_M0*col_M0; ++i){
printf("mutl_scal_matrix_matrix_col_based M0[%d] = %f\n", i , M0[i]);
}
for(i = 0; i < rows_M1*col_M1; ++i)
printf("mutl_scal_matrix_matrix_col_based: M1[%d] = (%f + i%f)\n", i , creal(M1[i]), cimag(M1[i]));
#endif
cblas_cgemm(CblasColMajor, transa, transb, rows_M0, col_M1, col_M0, &alpha, D_0_complex, rows_M0, M1, col_M0, &beta, Result, rows_M0);
#ifdef DEBUG_PREPROC
for(i = 0; i < rows_M0*col_M1; ++i)
printf("mutl_scal_matrix_matrix_col_based: result[%d] = (%f + i%f)\n", i , creal(Result[i]), cimag(Result[i]));
#endif
}
......@@ -262,108 +275,154 @@ void mutl_matrix_matrix_col_based(float complex* M0, float complex* M1, int rows
void compute_MMSE(float complex* H, int order_H, float sigma2, float complex* W_MMSE)
{
int N = order_H;
float complex* H_hermH_sigmaI = malloc(N*N*sizeof(float complex));
float complex* H_herm = malloc(N*N*sizeof(float complex));
float complex* H_hermH_sigmaI = calloc(N*N, sizeof(float complex));
float complex* H_herm = calloc(N*N, sizeof(float complex));
H_hermH_plus_sigma2I(N, N, H, sigma2, H_hermH_sigmaI);
#ifdef DEBUG_PREPROC
int i =0;
for(i=0;i<N*N;i++)
printf(" H_hermH_sigmaI[%d] = (%f + i%f)\n", i , creal(H_hermH_sigmaI[i]), cimag(H_hermH_sigmaI[i]));
int i = 0;
for(i = 0;i < N*N; ++i)
printf("compute_MMSE: H_hermH_sigmaI[%d] = (%f + i%f)\n", i , creal(H_hermH_sigmaI[i]), cimag(H_hermH_sigmaI[i]));
#endif
conjugate_transpose (N, H, H_herm); //equals H_herm
conjugate_transpose (N, N, H, H_herm); //equals H_herm
#ifdef DEBUG_PREPROC
for(i=0;i<N*N;i++)
printf(" H_herm[%d] = (%f + i%f)\n", i , creal(H_herm[i]), cimag(H_herm[i]));
for(i = 0;i < N*N;i++)
printf("compute_MMSE: H_herm[%d] = (%f + i%f)\n", i , creal(H_herm[i]), cimag(H_herm[i]));
#endif
lin_eq_solver(N, H_hermH_sigmaI, H_herm, W_MMSE);
#ifdef DEBUG_PREPROC
for(i=0;i<N*N;i++)
printf(" W_MMSE[%d] = (%f + i%f)\n", i , creal(W_MMSE[i]), cimag(W_MMSE[i]));
for(i = 0;i < N*N; ++i)
printf("compute_MMSE: W_MMSE[%d] = (%f + i%f)\n", i , creal(W_MMSE[i]), cimag(W_MMSE[i]));
#endif
free(H_hermH_sigmaI);
free(H_herm);
}
#if 0
void compute_white_filter(float complex* H_re,
int order_H,
float sqrt_float(float x)
{
float sqrt_x = 0.0;
sqrt_x = (float)(sqrt((double)(x)));
return sqrt_x;
}
void compute_white_filter(float complex* H0_re,
float complex* H1_re,
float sigma2,
int n_rx,
int n_tx,
float complex* W_Wh_0_re,
float complex* W_Wh_1_re){
int aatx, aarx, re;
int i,j;
int M =n_rx;
int N = n_tx;
int sigma2=noise_power;
float complex *H0_re = malloc(n_rx*(n_tx>>2)*sizeof(float complex));
float complex *H1_re = malloc(n_rx*(n_tx>>2)*sizeof(float complex));
float complex *R_corr_col_n_0_re = malloc(n_rx*n_tx*sizeof(float complex));
float complex *R_corr_col_n_1_re = malloc(n_rx*n_tx*sizeof(float complex));
float complex *U_0_re = malloc(n_rx*n_tx*sizeof(float complex));
float complex *U_1_re = malloc(n_rx*n_tx*sizeof(float complex));
float complex *U_0_herm_re = malloc(n_rx*n_tx*sizeof(float complex));
float complex *U_1_herm_re = malloc(n_rx*n_tx*sizeof(float complex));
float complex *D_0_re = malloc(n_rx*n_tx*sizeof(float complex));
float complex *D_1_re = malloc(n_rx*n_tx*sizeof(float complex));
float complex *W_Wh_0_re = malloc(n_rx*n_tx*sizeof(float complex));
float complex *W_Wh_1_re = malloc(n_rx*n_tx*sizeof(float complex));
for (aatx=0; aatx<n_tx/2; aatx++){
for (aarx=0; aarx<n_rx; aarx++) {
H0_re[aatx*n_rx + aarx] = H_re[aatx*n_rx + aarx][re]; // H0 gets [0 1 2 3; 4,5,6,7].' coefficients of H
H1_re[aatx*n_rx + aarx] = H_re[aatx*n_rx + aarx + 8][re]; // H1 gets [8 9 10 11; 12, 13, 14, 15].' coefficients of H
if (re == 0)
printf("ant %d, H_re = (%f + i%f) \n", aatx*n_rx + aarx, creal(H[aatx*n_rx + aarx][re]), cimag(H[aatx*n_rx + aarx][re]));
}
}
float sigma = 0.0;
int i;
float complex *R_corr_col_n_0_re = calloc(n_rx*n_tx, sizeof(float complex));
float complex *R_corr_col_n_1_re = calloc(n_rx*n_tx, sizeof(float complex));
float complex *U_0_re = calloc(n_rx*n_tx, sizeof(float complex));
float complex *U_1_re = calloc(n_rx*n_tx, sizeof(float complex));
float complex *U_0_herm_re = calloc(n_rx*n_tx, sizeof(float complex));
float complex *U_1_herm_re = calloc(n_rx*n_tx, sizeof(float complex));
float *D_0_re = calloc(n_rx*n_tx, sizeof(float));
float *D_1_re = calloc(n_rx*n_tx, sizeof(float));
float *D_0_re_inv_sqrt = calloc(n_rx*n_tx, sizeof(float));
float *D_1_re_inv_sqrt = calloc(n_rx*n_tx, sizeof(float));
#ifdef DEBUG_PREPROC
printf("compute_white_filter: sigma2 = %f\n", sigma2);
for(i=0; i<n_rx*n_tx/2; i++){
printf("compute_white_filter: H1_re[%d] = (%f + i%f)\n", i , creal(H1_re[i]), cimag(H1_re[i]));
printf("compute_white_filter: H0_re[%d] = (%f + i%f)\n", i , creal(H0_re[i]), cimag(H0_re[i]));
}
#endif
HH_herm_plus_sigma2I(n_rx, n_tx/2, H1_re, sigma2, R_corr_col_n_0_re);
HH_herm_plus_sigma2I(n_rx, n_tx/2, H0_re, sigma2, R_corr_col_n_1_re);
#ifdef DEBUG_PREPROC
for(i=0;i<n_rx*n_tx;i++){
printf("compute_white_filter: R_corr_col_n_0_re[%d] = (%f + i%f)\n", i , creal(R_corr_col_n_0_re[i]), cimag(R_corr_col_n_0_re[i]));
printf("compute_white_filter: R_corr_col_n_1_re[%d] = (%f + i%f)\n", i , creal(R_corr_col_n_1_re[i]), cimag(R_corr_col_n_1_re[i]));
}
//HH_herm_plus_sigma2I(n_rx, (n_tx>>2), H1_re, sigma2, R_corr_col_n_0_re);
HH_herm_plus_sigma2I(n_rx, (n_tx>>2), H0_re, sigma2, R_corr_col_n_1_re);
#endif
eigen_vectors_values(n_rx, R_corr_col_n_0_re, U_0_re, D_0_re);
eigen_vectors_values(n_rx, R_corr_col_n_1_re, U_1_re, D_1_re);
transpose (n_rx, U_0_re, U_0_herm_re);
transpose (n_rx, U_1_re, U_1_herm_re);
#ifdef DEBUG_PREPROC
for(i=0;i<n_rx*n_tx;i++){
printf("compute_white_filter: U_0_re[%d] = (%f + i%f)\n", i , creal(U_0_re[i]), cimag(U_0_re[i]));
printf("compute_white_filter: D_0_re[%d] = (%f + i%f)\n", i , creal(D_0_re[i]), cimag(D_0_re[i]));
}
#endif
conjugate_transpose(n_rx, n_tx, U_0_re, U_0_herm_re);
conjugate_transpose(n_rx, n_tx, U_1_re, U_1_herm_re);
#ifdef DEBUG_PREPROC
for(i = 0;i < n_rx*n_tx; i++){
printf("compute_white_filter: U_0_herm_re[%d] = (%f + i%f)\n", i , creal(U_0_herm_re[i]), cimag(U_0_herm_re[i]));
}
#endif
sigma = (float)(sqrt((double)(sigma2)));
if (sigma <= 0.00001){
sigma = 0.00001;
}
/*The inverse of a diagonal matrix is obtained by replacing each element in the diagonal with its reciprocal.
A square root of a diagonal matrix is given by the diagonal matrix, whose diagonal entries are just the square
roots of the original matrix.*/
//The inverse of a diagonal matrix is obtained by replacing each element in the diagonal with //its reciprocal.
//A square root of a diagonal matrix is given by the diagonal matrix, whose diagonal entries are //just the square
//roots of the original matrix.
//printf ("This linear preprocessing is line %d.\n", __LINE__);
for (i = 0; i < n_rx*n_tx; i += (n_rx + 1)){
D_0_re_inv_sqrt[0] = sqrt_float(1/D_0_re_inv[0]);
D_0_re_inv_sqrt[5] = sqrt_float(1/D_0_re_inv[5]);
D_0_re_inv_sqrt[10] = sqrt_float(1/D_0_re_inv[10]);
D_0_re_inv_sqrt[15] = sqrt_float(1/D_0_re_inv[15]);
if (D_0_re[i] <= 0.00001){
D_0_re[i] = 0.00001;
}
if (D_1_re[i] <= 0.00001){
D_1_re[i] = 0.00001;
}
D_1_re_inv[0] = sqrt_float(1/D_1_re_inv[0]);
D_1_re_inv[5] = sqrt_float(1/D_1_re_inv[5]);
D_1_re_inv[10] = sqrt_float(1/D_1_re_inv[10]);
D_1_re_inv[15] = sqrt_float(1/D_1_re_inv[15]);
D_0_re_inv_sqrt[i] = sqrt_float(1/D_0_re[i]);
D_1_re_inv_sqrt[i] = sqrt_float(1/D_1_re[i]);
}
now only to multiply
free(H0);
free(H1);
free(R_corr_col_n_0);
free(R_corr_col_n_1);
}
#ifdef DEBUG_PREPROC
for(i = 0;i <n_rx*n_tx; i++){
printf("compute_white_filter: D_0_re_inv_sqrt[%d] = %f\n", i , D_0_re_inv_sqrt[i]);
}
#endif
float sqrt_float(float x, float sqrt_x)
{
sqrt_x = (float)(sqrt((double)(x)));
return sqrt_x;
mutl_scal_matrix_matrix_col_based(D_0_re_inv_sqrt, U_0_herm_re, sigma, n_rx, n_tx, n_rx, n_tx, W_Wh_0_re);
#ifdef DEBUG_PREPROC
for(i = 0;i < n_rx*n_tx; i++){
printf("compute_white_filter: W_Wh_0_re[%d] = (%f + i%f)\n", i , creal(W_Wh_0_re[i]), cimag(W_Wh_0_re[i]));
}
#endif
mutl_scal_matrix_matrix_col_based(D_1_re_inv_sqrt, U_1_herm_re, sigma, n_rx, n_tx, n_rx, n_tx, W_Wh_1_re);
free(R_corr_col_n_0_re);
free(R_corr_col_n_1_re);
free(U_0_herm_re);
free(U_1_herm_re);
free(D_0_re_inv_sqrt);
free(D_1_re_inv_sqrt);
free(U_0_re);
free(U_1_re);
free(D_0_re);
free(D_1_re);
}
......@@ -9,7 +9,7 @@
/* FUNCTIONS FOR LINEAR PREPROCESSING: MMSE, WHITENNING, etc*/
void transpose(int N, float complex *A, float complex *Result);
void conjugate_transpose(int N, float complex *A, float complex *Result);
void conjugate_transpose (int rows_A, int col_A, float complex *A, float complex *Result);
void H_hermH_plus_sigma2I(int N, int M, float complex *A, float sigma2, float complex *Result);
......@@ -26,9 +26,19 @@ void mutl_matrix_matrix_row_based(float complex* M0, float complex* M1, int rows
/* mutl_matrix_matrix_col_based performs multiplications matrix is column-oriented H[0], H[2]; H[1], H[3]*/
void mutl_matrix_matrix_col_based(float complex* M0, float complex* M1, int rows_M0, int col_M0, int rows_M1, int col_M1, float complex* Result );
void mutl_scal_matrix_matrix_col_based(float complex* M0, float complex* M1, float complex alpha, int rows_M0, int col_M0, int rows_M1, int col_M1, float complex* Result);
void compute_MMSE(float complex* H, int order_H, float sigma2, float complex* W_MMSE);
void compute_white_filter(float complex* H, int order_H, float sigma2, float complex* U_1, float complex* D_1);
float sqrt_float(float x);
void compute_white_filter(float complex* H0_re,
float complex* H1_re,
float sigma2,
int n_rx,
int n_tx,
float complex* W_Wh_0_re,
float complex* W_Wh_1_re);
void mmse_processing_oai(LTE_UE_PDSCH *pdsch_vars,
LTE_DL_FRAME_PARMS *frame_parms,
......@@ -57,38 +67,41 @@ void rxdataF_to_float(int32_t **rxdataF_ext,
void chan_est_to_float(int32_t **dl_ch_estimates_ext,
float complex **dl_ch_estimates_ext_f,
int n_tx,
int n_rx,
int length,
int start_point);
void float_to_chan_est(int32_t **dl_ch_estimates_ext,
float complex **dl_ch_estimates_ext_f,
int n_tx,
int n_rx,
int length,
int start_point);
void float_to_rxdataF(int32_t **rxdataF_ext,
float complex **rxdataF_f,
int n_tx,
int n_rx,
int length,
int start_point);
uint8_t n_tx,
uint8_t n_rx,
int32_t length,
int32_t start_point);
void mult_mmse_rxdataF(float complex** Wmmse,
float complex** rxdataF_ext_f,
void float_to_chan_est(float complex **chan_est_flp,
int32_t **result,
int n_tx,
int n_rx,
int length,
int start_point);
void mult_mmse_chan_est(float complex** Wmmse,
float complex** dl_ch_estimates_ext_f,
int n_tx,
int n_rx,
int length,
int start_point);
void float_to_rxdataF(float complex **rxdataF_flp,
int32_t **result,
uint8_t n_tx,
uint8_t n_rx,
int32_t length,
int32_t start_point);
void mult_filter_chan_est(float complex **W,
float complex **chan_est_flp,
float complex **result,
uint8_t n_tx,
uint8_t n_rx,
int32_t n_col_chan_est_flp,
int32_t length,
int32_t start_point);
void mult_filter_rxdataF(float complex **W,
float complex **rxdataF_flp,
float complex **result,
uint8_t n_tx,
uint8_t n_rx,
int32_t length,
int32_t start_point);
void mmse_processing_core(int32_t **rxdataF_ext,
int32_t **dl_ch_estimates_ext,
......@@ -98,24 +111,27 @@ void mmse_processing_core(int32_t **rxdataF_ext,
int length,
int start_point);
void mmse_processing_core_flp(float complex** rxdataF_ext_flcpx,
float complex **H,
int32_t **rxdataF_ext,
int32_t **dl_ch_estimates_ext,
void mmse_processing_core_flp(float complex** rxdataF_flp,
float complex **chan_est_flp,
int32_t **rxdataF_filt_fp,
int32_t **chan_est_eff_fp,
float noise_power,
uint8_t n_tx,
uint8_t n_rx,
int32_t length,
int32_t start_point);
void whitening_processing_core_flp(float complex **rxdataF_flp,
float complex **chan_est_flp_0,
float complex **chan_est_flp_1,
int32_t **rxdataF_filt_fp_0,
int32_t **rxdataF_filt_fp_1,
int32_t **chan_est_eff_fp_0,
int32_t **chan_est_eff_fp_1,
float sigma2,
int n_tx,
int n_rx,
int length,
int start_point);
uint8_t n_tx,
uint8_t n_rx,
int32_t length,
int32_t start_point);
void whitening_processing_core_flp(float complex** rxdataF_ext_flcpx,
float complex **H,
int32_t **rxdataF_ext,
int32_t **dl_ch_estimates_ext,
float sigma2,
int n_tx,
int n_rx,
int length,
int start_point);
float sqrt_float(float x, float sqrt_x);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment