dac.c 8.77 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

lfarizav's avatar
lfarizav committed
22
//#define DEBUG_DAC
23
#include <math.h>
24
#include <stdio.h>
25 26
#include "PHY/TOOLS/defs.h"

27 28
void dac(double *s_re[2],
         double *s_im[2],
29 30 31 32 33 34 35 36 37
         uint32_t **input,
         uint32_t input_offset,
         uint32_t nb_tx_antennas,
         uint32_t length,
         double amp_dBm,
         uint8_t B,
         uint32_t meas_length,
         uint32_t meas_offset)
{
38 39 40 41 42

  int i;
  int aa;
  double V=0.0,amp;

43 44
  for (i=0; i<length; i++) {
    for (aa=0; aa<nb_tx_antennas; aa++) {
45 46 47 48 49 50
      s_re[aa][i] = ((double)(((short *)input[aa]))[((i+input_offset)<<1)])/(1<<(B-1));
      s_im[aa][i] = ((double)(((short *)input[aa]))[((i+input_offset)<<1)+1])/(1<<(B-1));

    }
  }

51 52 53
  for (i=meas_offset; i<meas_offset+meas_length; i++) {
    for (aa=0; aa<nb_tx_antennas; aa++) {
      V= V + (s_re[aa][i]*s_re[aa][i]) + (s_im[aa][i]*s_im[aa][i]);
54 55
    }
  }
56

57 58 59 60
  V /= (meas_length);
#ifdef DEBUG_DAC
  printf("DAC: 10*log10(V)=%f (%f)\n",10*log10(V),V);
#endif
61

62 63 64 65 66 67 68
  if (V) {
    amp = pow(10.0,.1*amp_dBm)/V;
    amp = sqrt(amp);
  } else {
    amp = 1;
  }

69 70
  for (i=0; i<length; i++) {
    for (aa=0; aa<nb_tx_antennas; aa++) {
71 72 73 74 75
      s_re[aa][i] *= amp;
      s_im[aa][i] *= amp;
    }
  }
}
lfarizav's avatar
lfarizav committed
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
#define dac_SSE
#ifdef  dac_SSE
//This implementation of dac_fixed_gain using SSE does not work
double dac_fixed_gain(double *s_re[2],
                      double *s_im[2],
                      uint32_t **input,
                      uint32_t input_offset,
                      uint32_t nb_tx_antennas,
                      uint32_t length,
                      uint32_t input_offset_meas,
                      uint32_t length_meas,
                      uint8_t B,
                      double txpwr_dBm,
                      int NB_RE)
{
91

lfarizav's avatar
lfarizav committed
92 93 94
  int i;
  int aa;
  double amp,amp1,div;
95
  __m128d input_re128, input_im128;
lfarizav's avatar
lfarizav committed
96 97 98 99 100 101 102 103 104 105 106 107 108 109

  amp = //sqrt(NB_RE)*pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); //this is amp per tx antenna
    pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); //this is amp per tx antenna
  amp1 = 0;

  for (aa=0; aa<nb_tx_antennas; aa++) {
    amp1 += sqrt((double)signal_energy((int32_t*)&input[aa][input_offset_meas],length_meas)/NB_RE);
  }

  amp1/=nb_tx_antennas;

  div=amp/amp1;
  for (i=0; i<(length>>1); i++) {
    for (aa=0; aa<nb_tx_antennas; aa++) {
110 111
      input_re128=_mm_set_pd(((double)(((short *)input[aa]))[(((2*i+1)+input_offset)<<1)]),((double)(((short *)input[aa]))[((2*i+input_offset)<<1)]));
      input_im128=_mm_set_pd(((double)(((short *)input[aa]))[(((2*i+1)+input_offset)<<1)+1]),((double)(((short *)input[aa]))[((2*i+input_offset)<<1)+1]));
lfarizav's avatar
lfarizav committed
112 113 114 115 116 117 118 119
      input_re128=_mm_mul_pd(input_re128,_mm_set1_pd(div));
      input_im128=_mm_mul_pd(input_im128,_mm_set1_pd(div));
      _mm_storeu_pd(&s_re[aa][2*i],input_re128);
      _mm_storeu_pd(&s_im[aa][2*i],input_im128);
      //s_re[aa][i] = amp*((double)(((short *)input[aa]))[((i+input_offset)<<1)])/amp1; ///(1<<(B-1));
      //s_im[aa][i] = amp*((double)(((short *)input[aa]))[((i+input_offset)<<1)+1])/amp1; ///(1<<(B-1));
    }
  }
120 121
      /*for (i=0;i<length;i++)
      	printf(" s_re_out[%d] %e, s_im_out[%d] %e, input_re[%d] %e, input_im[%d] %e\n",i,s_re[0][i],i,s_im[0][i],i,((double)(((short *)input[0]))[((i+input_offset)<<1)]),i,((double)(((short *)input[0]))[((i+input_offset)<<1)+1]));*/
lfarizav's avatar
lfarizav committed
122 123 124 125 126
  //  printf("ener %e\n",signal_energy_fp(s_re,s_im,nb_tx_antennas,length,0));

  return(signal_energy_fp(s_re,s_im,nb_tx_antennas,length_meas,0)/NB_RE);
}
#else
127 128
double dac_fixed_gain(double *s_re[2],
                      double *s_im[2],
129 130 131 132 133 134 135 136 137 138
                      uint32_t **input,
                      uint32_t input_offset,
                      uint32_t nb_tx_antennas,
                      uint32_t length,
                      uint32_t input_offset_meas,
                      uint32_t length_meas,
                      uint8_t B,
                      double txpwr_dBm,
                      int NB_RE)
{
139 140 141

  int i;
  int aa;
142
  double amp,amp1,div;
143

144 145
  amp = //sqrt(NB_RE)*pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); //this is amp per tx antenna
    pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); //this is amp per tx antenna
146
  amp1 = 0;
147 148

  for (aa=0; aa<nb_tx_antennas; aa++) {
149
    amp1 += sqrt((double)signal_energy((int32_t*)&input[aa][input_offset_meas],length_meas)/NB_RE);
150
  }
151

152
  amp1/=nb_tx_antennas;
153

154
  //  printf("DAC: amp1 %f dB (%d,%d), tx_power %f\n",20*log10(amp1),input_offset,input_offset_meas,txpwr_dBm);
155 156 157 158 159 160

  /*
    if (nb_tx_antennas==2)
      amp1 = AMP/2;
    else if (nb_tx_antennas==4)
      amp1 = ((AMP*ONE_OVER_SQRT2_Q15)>>16);
161
    else //assume (nb_tx_antennas==1)
162 163 164 165
      amp1 = ((AMP*ONE_OVER_SQRT2_Q15)>>15);
    amp1 = amp1*sqrt(512.0/300.0); //account for loss due to null carriers
    //printf("DL: amp1 %f dB (%d,%d), tx_power %f\n",20*log10(amp1),input_offset,input_offset_meas,txpwr_dBm);
  */
166

167
  div=amp/amp1;
168 169
  for (i=0; i<length; i++) {
    for (aa=0; aa<nb_tx_antennas; aa++) {
170 171
      s_re[aa][i] = div*((double)(((short *)input[aa]))[((i+input_offset)<<1)]); ///(1<<(B-1));
      s_im[aa][i] = div*((double)(((short *)input[aa]))[((i+input_offset)<<1)+1]); ///(1<<(B-1));
lfarizav's avatar
lfarizav committed
172 173
      //if (i<1024)
	//printf("s_re [%d]%e\n",i,s_re[aa][i]);
174
    }
lfarizav's avatar
lfarizav committed
175
  }      	
176 177
      /*for (i=0;i<length;i++)
      	printf(" s_re_out[%d] %e, s_im_out[%d] %e, input_re[%d] %e, input_im[%d] %e\n",i,s_re[0][i],i,s_im[0][i],i,((double)(((short *)input[0]))[((i+input_offset)<<1)]),i,((double)(((short *)input[0]))[((i+input_offset)<<1)+1]));*/
178 179
  //  printf("ener %e\n",signal_energy_fp(s_re,s_im,nb_tx_antennas,length,0));

180
  return(signal_energy_fp(s_re,s_im,nb_tx_antennas,length_meas,0)/NB_RE);
181
}
lfarizav's avatar
lfarizav committed
182
#endif
lfarizav's avatar
lfarizav committed
183 184 185 186 187 188 189 190 191 192
double dac_fixed_gain_prach(double *s_re[2],
                      double *s_im[2],
                      uint32_t *input,
                      uint32_t input_offset,
                      uint32_t nb_tx_antennas,
                      uint32_t length,
                      uint32_t input_offset_meas,
                      uint32_t length_meas,
                      uint8_t B,
                      double txpwr_dBm,
lfarizav's avatar
lfarizav committed
193 194
                      int NB_RE,
		      int ofdm_symbol_size)
lfarizav's avatar
lfarizav committed
195 196 197 198 199
{

  int i;
  int aa;
  double amp,amp1;
lfarizav's avatar
lfarizav committed
200
  int k;
lfarizav's avatar
lfarizav committed
201 202 203 204 205 206

  amp = //sqrt(NB_RE)*pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); //this is amp per tx antenna
    pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); //this is amp per tx antenna
  amp1 = 0;

  for (aa=0; aa<nb_tx_antennas; aa++) {
lfarizav's avatar
lfarizav committed
207
    amp1 += sqrt((double)signal_energy_prach((int32_t*)&input[input_offset_meas],length_meas)/NB_RE);
lfarizav's avatar
lfarizav committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
  }

  amp1/=nb_tx_antennas;

  //  printf("DAC: amp1 %f dB (%d,%d), tx_power %f\n",20*log10(amp1),input_offset,input_offset_meas,txpwr_dBm);

  /*
    if (nb_tx_antennas==2)
      amp1 = AMP/2;
    else if (nb_tx_antennas==4)
      amp1 = ((AMP*ONE_OVER_SQRT2_Q15)>>16);
    else //assume (nb_tx_antennas==1)
      amp1 = ((AMP*ONE_OVER_SQRT2_Q15)>>15);
    amp1 = amp1*sqrt(512.0/300.0); //account for loss due to null carriers
    //printf("DL: amp1 %f dB (%d,%d), tx_power %f\n",20*log10(amp1),input_offset,input_offset_meas,txpwr_dBm);
  */
lfarizav's avatar
lfarizav committed
224 225 226
#ifdef DEBUG_DAC
  printf("DAC: input_offset %d, amp %e, amp1 %e\n",input_offset,amp,amp1);
#endif
lfarizav's avatar
lfarizav committed
227
  k=input_offset;
lfarizav's avatar
lfarizav committed
228
  for (i=0; i<length*2; i+=2) {
lfarizav's avatar
lfarizav committed
229
    for (aa=0; aa<nb_tx_antennas; aa++) {
lfarizav's avatar
lfarizav committed
230 231
      s_re[aa][i/2] = amp*((double)(((short *)input))[((k))])/amp1; ///(1<<(B-1));
      s_im[aa][i/2] = amp*((double)(((short *)input))[((k))+1])/amp1; ///(1<<(B-1));
lfarizav's avatar
lfarizav committed
232 233
#ifdef DEBUG_DAC
      if(i<20)
lfarizav's avatar
lfarizav committed
234
      	printf("DAC[%d]: input (%d,%d). output (%e,%e)\n",i/2,(((short *)input))[((k))],(((short *)input))[((k))+1],s_re[aa][i/2],s_im[aa][i/2]);
lfarizav's avatar
lfarizav committed
235
      if (i>length*2-20&&i<length*2)
lfarizav's avatar
lfarizav committed
236
	printf("DAC[%d]: input (%d,%d). output (%e,%e)\n",i/2,(((short *)input))[((k))],(((short *)input))[((k))+1],s_re[aa][i/2],s_im[aa][i/2]);
lfarizav's avatar
lfarizav committed
237
#endif
lfarizav's avatar
lfarizav committed
238 239 240
      k+=2;
      if (k==12*2*ofdm_symbol_size)
 	k=0;
lfarizav's avatar
lfarizav committed
241 242 243 244 245 246 247
    }
  }

  //  printf("ener %e\n",signal_energy_fp(s_re,s_im,nb_tx_antennas,length,0));

  return(signal_energy_fp(s_re,s_im,nb_tx_antennas,length_meas,0)/NB_RE);
}