convert_SMVB.c 5.84 KB
Newer Older
Laurent THOMAS's avatar
Laurent THOMAS committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
/*
* 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.1  (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
*
* Author and copyright: Laurent Thomas, open-cells.com
*
* 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
*/


#include <common/utils/simple_executable.h>
#include <sys/sendfile.h>

volatile int             oai_exit = 0;

#define shift 4
int32_t signal_energy(int32_t *input,uint32_t length) {
  int32_t i;
  int32_t temp,temp2;
  register __m64 mm0,mm1,mm2,mm3;
  __m64 *in = (__m64 *)input;
  mm0 = _mm_setzero_si64();//pxor(mm0,mm0);
  mm3 = _mm_setzero_si64();//pxor(mm3,mm3);

  for (i=0; i<length>>1; i++) {
    mm1 = in[i];
    mm2 = mm1;
    mm1 = _m_pmaddwd(mm1,mm1);
    mm1 = _m_psradi(mm1,shift);// shift any 32 bits blocs of the word by the value shift
    mm0 = _m_paddd(mm0,mm1);// add the two 64 bits words 4 bytes by 4 bytes
    //    mm2 = _m_psrawi(mm2,shift_DC);
    mm3 = _m_paddw(mm3,mm2);// add the two 64 bits words 2 bytes by 2 bytes
  }

  mm1 = mm0;
  mm0 = _m_psrlqi(mm0,32);
  mm0 = _m_paddd(mm0,mm1);
  temp = _m_to_int(mm0);
  temp/=length;
  temp<<=shift;   // this is the average of x^2
  // now remove the DC component
  mm2 = _m_psrlqi(mm3,32);
  mm2 = _m_paddw(mm2,mm3);
  mm2 = _m_pmaddwd(mm2,mm2);
  temp2 = _m_to_int(mm2);
  temp2/=(length*length);
  //  temp2<<=(2*shift_DC);
  temp -= temp2;
  _mm_empty();
  _m_empty();
  return((temp>0)?temp:1);
}

#define RS_head 256
void write_RS_header(int fd, ssize_t sz, int samplingRate) {
  const char l1[]="{TYPE: SMU-WV,0}";
  const char l2[]="{COMMENT: Generated by OAI}";
  const char l3[]="{DATE: %Y-%m-%d;%H:%M:%S}";
  const char l4[]="{LEVEL OFFS: 0.000000,0.00000}";
  const char l5[]="{CLOCK: %d}";
  const char l6[]="{SAMPLES: %ld}";
  const char l7[]="{WAVEFORM-%ld: #";
  write(fd,l1,strlen(l1));
  write(fd,l2,strlen(l2));
  time_t t=time(NULL);
  struct tm *tmp=localtime(&t);
  AssertFatal(tmp != NULL,"");
  char outstr[200];
  strftime(outstr, sizeof(outstr), l3, tmp);
  write(fd,outstr,strlen(outstr));
  write(fd,l4,strlen(l4));
  sprintf(outstr,l5,samplingRate);
  write(fd,outstr,strlen(outstr));
  sprintf(outstr,l6,sz);
  write(fd,outstr,strlen(outstr));
  sprintf(outstr,l7,sz*4+1);
  for (int i=lseek(fd,0,SEEK_CUR)+strlen(outstr); i<RS_head; i++)
    write(fd," ",1);
  write(fd,outstr,strlen(outstr));
}

int main(int argc, char *argv[]) {
  if(argc < 4) {
    printf("This program converts\n a stored I/Q file in rfsimulator saved IQ format or\n a raw I/Q file (signed 16bits)\nto R&S format\nNeed parameters: source file, destination file, sampling rate in Hz \n");
    exit(1);
  }

  int fdIn=open(argv[1],O_RDONLY);
  AssertFatal(fdIn != -1, "file: %s", argv[1]);
  off_t fileSize=lseek(fdIn, 0, SEEK_END);
  lseek(fdIn, 0, SEEK_SET);

  int fdOut=creat(argv[2], 0660);
  AssertFatal(fdOut != -1, "file: %s", argv[1]);

  int samplingRate=atoi(argv[3]);
  boolean_t raw=true;
  uint64_t magic;
  read(fdIn, &magic, sizeof(magic));
  if ( magic== UE_MAGICDL || magic == UE_MAGICUL || magic== ENB_MAGICDL || magic == ENB_MAGICUL )
    raw=false;
  lseek(fdIn, 0, SEEK_SET);
  
  if (raw) {
    // sequence of 2*16 bits ints, as R&S we need only to add the header
    write_RS_header(fdOut, fileSize, samplingRate);
    ssize_t bytesCopied=0;
    // We could consider rescaling
    while (bytesCopied != fileSize) { 
      ssize_t res = sendfile(fdOut, fdIn, &bytesCopied, fileSize);
      AssertFatal(res>0,"");
    }
  } else {
    samplesBlockHeader_t header, firstHeader;
    int bufSize=100000;
    void *buff=malloc(bufSize);
    int ret=read(fdIn,&firstHeader,sizeof(header));
    AssertFatal(ret== sizeof(header),"");
    lseek(fdIn, 0, SEEK_SET);
    AssertFatal(firstHeader.nbAnt==1, "R&S SMBV is one Tx\n");
    uint64_t timestamp=firstHeader.timestamp;
    uint32_t zero=0,zeros[64]={0};

    // Reserve room for the header
    lseek(fdOut, RS_head, SEEK_SET);
    int nb=0;
    while (read(fdIn,&header,sizeof(header)) == sizeof(header)) {
      int dataSize=sizeof(int32_t)*header.size*header.nbAnt;
      AssertFatal(header.nbAnt==1,"");
      if (dataSize>bufSize) {
	void *new_buff = realloc(buff, dataSize);
	if (new_buff == NULL)
	  AssertFatal(false, "Could not reallocate");
	else
	  buff = new_buff;
      }
      while (timestamp+64<header.timestamp){
	write(fdOut,&zeros,sizeof(zeros));
	timestamp+=64;
      }
      while (timestamp <header.timestamp){
	write(fdOut,&zero,sizeof(zero));
	timestamp++;
      }
      ssize_t ret=read(fdIn,buff,dataSize);
      AssertFatal(ret == dataSize, "");
      for (int i=0; i<header.size*header.nbAnt*2; i++)
        ((int16_t *)buff)[i]*=16;
      ret=write(fdOut, buff, dataSize);
      AssertFatal(ret == dataSize, "");
      timestamp+=header.size;
      nb++;
    }
    printf("converted %ld samples, control: %ld, %d, %ld\n", timestamp, header.size+header.timestamp, nb, firstHeader.timestamp);
    free(buff);
    lseek(fdOut, 0, SEEK_SET);
    write_RS_header(fdOut,timestamp-firstHeader.timestamp, samplingRate);
    lseek(fdOut, 0, SEEK_END);
  }

  write(fdOut,"}",1);
  close(fdOut);
  close(fdIn);
  return 0;
}