LCOV - code coverage report
Current view: top level - src - receiver.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 0 77 0.0 %
Date: 2015-01-05 16:01:02 Functions: 0 6 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 60 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * receiver.cpp - receiver transformation class implementation
       3                 :            :  *
       4                 :            :  * Copyright (C) 2009 Dirk Schaefer <schad@5pm.de>
       5                 :            :  * Copyright (C) 2009 Stefan Jahn <stefan@lkcc.org>
       6                 :            :  *
       7                 :            :  * This is free software; you can redistribute it and/or modify
       8                 :            :  * it under the terms of the GNU General Public License as published by
       9                 :            :  * the Free Software Foundation; either version 2, or (at your option)
      10                 :            :  * any later version.
      11                 :            :  *
      12                 :            :  * This software is distributed in the hope that it will be useful,
      13                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :            :  * GNU General Public License for more details.
      16                 :            :  *
      17                 :            :  * You should have received a copy of the GNU General Public License
      18                 :            :  * along with this package; see the file COPYING.  If not, write to
      19                 :            :  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
      20                 :            :  * Boston, MA 02110-1301, USA.
      21                 :            :  *
      22                 :            :  * $Id$
      23                 :            :  *
      24                 :            :  */
      25                 :            : 
      26                 :            : #if HAVE_CONFIG_H
      27                 :            : # include <config.h>
      28                 :            : #endif
      29                 :            : 
      30                 :            : #include <stdio.h>
      31                 :            : #include <stdlib.h>
      32                 :            : #include <string.h>
      33                 :            : #include <cmath>
      34                 :            : #include <cstdint>
      35                 :            : 
      36                 :            : #include "consts.h"
      37                 :            : #include "object.h"
      38                 :            : #include "complex.h"
      39                 :            : #include "vector.h"
      40                 :            : #include "spline.h"
      41                 :            : #include "interpolator.h"
      42                 :            : #include "fourier.h"
      43                 :            : #include "receiver.h"
      44                 :            : 
      45                 :            : namespace qucs {
      46                 :            : 
      47                 :            : /* The function returns a power-of-two value which is equal or larger
      48                 :            :    than the given value.  The maximum returned value is 2^30. */
      49                 :          0 : int32_t emi::nearestbin32 (int x) {
      50                 :          0 :   int32_t boundary = 1 << 30;
      51                 :          0 :   int32_t current = 1;
      52         [ #  # ]:          0 :   if (x >= boundary) return boundary;
      53         [ #  # ]:          0 :   while (current < x) current <<= 1;
      54                 :          0 :   return current;
      55                 :            : }
      56                 :            : 
      57                 :            : /* Ideal filter construction for given center frequency, bandwidth and
      58                 :            :    the frequency for which the filter is evaluated. */
      59                 :          0 : nr_double_t emi::f_ideal (nr_double_t fc, nr_double_t bw, nr_double_t f) {
      60                 :          0 :   nr_double_t lo = fc - bw / 2;
      61                 :          0 :   nr_double_t hi = fc + bw / 2;
      62 [ #  # ][ #  # ]:          0 :   if (f >= lo && f < hi)
      63                 :          0 :     return 1.0;
      64                 :          0 :   return 0.0;
      65                 :            : }
      66                 :            : 
      67                 :            : /* Construction of a bandpass filter of 2nd order for given center
      68                 :            :    frequency, bandwidth and the frequency for which the filter is
      69                 :            :    evaluated. */
      70                 :          0 : nr_double_t emi::f_2ndorder (nr_double_t fc, nr_double_t bw, nr_double_t f) {
      71                 :          0 :   nr_double_t q = fc / bw;
      72                 :          0 :   nr_complex_t p = nr_complex_t (0, f / fc);
      73 [ #  # ][ #  # ]:          0 :   nr_complex_t w = p / q / (1.0 + p / q + p * p);
                 [ #  # ]
      74         [ #  # ]:          0 :   return norm (w);
      75                 :            : }
      76                 :            : 
      77                 :            : /* Construction of a gaussian filter for given center frequency,
      78                 :            :    bandwidth and the frequency for which the filter is evaluated. */
      79                 :          0 : nr_double_t emi::f_gauss (nr_double_t fc, nr_double_t bw, nr_double_t f) {
      80                 :          0 :   nr_double_t a = log (0.5) / bw / bw;
      81                 :          0 :   nr_double_t s = f - fc;
      82                 :          0 :   return exp (a * s * s);
      83                 :            : }
      84                 :            : 
      85                 :            : /* The function computes a EMI receiver spectrum based on the given
      86                 :            :    waveform in the time domain.  The number of points in the waveform
      87                 :            :    is required to be a power of two.  Also the samples are supposed
      88                 :            :    to be equidistant. */
      89                 :          0 : vector * emi::receiver (nr_double_t * ida, nr_double_t duration, int ilength) {
      90                 :            : 
      91                 :            :   int i, n, points;
      92                 :            :   nr_double_t fres;
      93 [ #  # ][ #  # ]:          0 :   vector * ed = new vector ();
      94                 :            : 
      95                 :          0 :   points = ilength;
      96                 :            : 
      97                 :            :   /* ilength must be a power of 2 - write wrapper later on */
      98         [ #  # ]:          0 :   fourier::_fft_1d (ida, ilength, 1); /* 1 = forward fft */
      99                 :            : 
     100                 :            :   /* start at first AC point (0 as DC point remains untouched)
     101                 :            :      additionally only half of the FFT result required */
     102         [ #  # ]:          0 :   for (i = 2; i < points; i++) {
     103                 :          0 :     ida[i] /= points / 2;
     104                 :            :   }
     105                 :            : 
     106                 :            :   /* calculate frequency step */
     107                 :          0 :   fres = 1.0 / duration;
     108                 :            : 
     109                 :            :   /* generate data vector; inplace calculation of magnitudes */
     110                 :          0 :   nr_double_t * d = ida;
     111         [ #  # ]:          0 :   for (n = 0, i = 0; i < points / 2; i++, n += 2){
     112                 :            :     /* abs value of complex number */
     113         [ #  # ]:          0 :     d[i] = xhypot (ida[n], ida[n + 1]);
     114                 :            :     /* vector contains complex values; thus every second value */
     115                 :            :   }
     116                 :            : 
     117                 :          0 :   points /= 2;
     118                 :            : 
     119                 :            :   /* define EMI settings */
     120                 :            :   struct settings settings[] = {
     121                 :            :     {   200, 150e3,   200,   200 },
     122                 :            :     { 150e3,  30e6,   9e3,   9e3 },
     123                 :            :     {  30e6,   1e9, 120e3, 120e3 },
     124                 :            :     {     0,     0,     0,      0}
     125                 :          0 :   };
     126                 :            : 
     127                 :            :   /* define EMI noise floor */
     128                 :          0 :   nr_double_t noise = std::pow (10.0, (-100.0 / 40.0)) * 1e-6;
     129                 :            : 
     130                 :            :   /* generate resulting data & frequency vector */
     131                 :            :   nr_double_t fcur, dcur;
     132                 :          0 :   int ei = 0;
     133                 :            : 
     134                 :            :   /* go through each EMI setting */
     135         [ #  # ]:          0 :   for (i = 0; settings[i].bandwidth != 0; i++ ) {
     136                 :            : 
     137                 :          0 :     nr_double_t bw = settings[i].bandwidth;
     138                 :          0 :     nr_double_t fstart = settings[i].start;
     139                 :          0 :     nr_double_t fstop = settings[i].stop;
     140                 :          0 :     nr_double_t fstep = settings[i].stepsize;
     141                 :            : 
     142                 :            :     /* go through frequencies */
     143         [ #  # ]:          0 :     for (fcur = fstart; fcur <= fstop; fcur += fstep) {
     144                 :            : 
     145                 :            :       /* calculate upper and lower frequency bounds */
     146                 :          0 :       nr_double_t lo = fcur - bw / 2;
     147                 :          0 :       nr_double_t hi = fcur + bw / 2;
     148         [ #  # ]:          0 :       if (hi < fres) continue;
     149                 :            : 
     150                 :            :       /* calculate indices covering current bandwidth */
     151                 :          0 :       int il = std::floor (lo / fres);
     152                 :          0 :       int ir = std::floor (hi / fres);
     153                 :            : 
     154                 :            :       /* right index (ri) greater 0 and left index less than points ->
     155                 :            :          at least part of data is within bandwidth indices */
     156 [ #  # ][ #  # ]:          0 :       if (ir >= 0 && il < points - 1) {
     157                 :            :         /* adjust indices to reside in the data array */
     158         [ #  # ]:          0 :         if (il < 0) il = 0;
     159         [ #  # ]:          0 :         if (ir > points - 1) ir = points - 1;
     160                 :            : 
     161                 :            :         /* sum-up the values within the bandwidth */
     162                 :          0 :         dcur = 0;
     163         [ #  # ]:          0 :         for (int j = 0; j < ir - il; j++){
     164                 :          0 :           nr_double_t f = fres * (il + j);
     165         [ #  # ]:          0 :           dcur += f_2ndorder (fcur, bw, f) * d[il + j];
     166                 :            :         }
     167                 :            : 
     168                 :            :         /* add noise to the result */
     169         [ #  # ]:          0 :         dcur += noise * sqrt (bw);
     170                 :            : 
     171                 :            :         /* save result */
     172         [ #  # ]:          0 :         ed->add (nr_complex_t (dcur, fcur));
     173                 :          0 :         ei++;
     174                 :            :       }
     175                 :            :     }
     176                 :            :   }
     177                 :            : 
     178                 :            :   /* returning values of function */
     179                 :          0 :   return ed;
     180                 :            : }
     181                 :            : 
     182                 :            : /* This is a wrapper for the basic EMI rceiver functionality.  It
     183                 :            :    takes an arbitraty waveform in the time domain and interpolates it
     184                 :            :    such, that its length results in a power of two elements. */
     185                 :          0 : vector * emi::receiver (vector * da, vector * dt, int len) {
     186                 :            : 
     187                 :          0 :   int i, nlen, olen =  da->getSize ();
     188                 :            : 
     189                 :            :   // don't allow less points than the actual length
     190         [ #  # ]:          0 :   if (len < da->getSize ()) len = da->getSize ();
     191                 :            : 
     192                 :            :   // find a power-of-two length
     193                 :          0 :   nlen = emi::nearestbin32 (len);
     194                 :            : 
     195                 :          0 :   nr_double_t tstart = real (dt->get (0));
     196                 :          0 :   nr_double_t tstop = real (dt->get (olen - 1));
     197                 :          0 :   nr_double_t duration = tstop - tstart;
     198                 :            : 
     199                 :            :   /* please note: interpolation is always performed in order to ensure
     200                 :            :      equidistant samples */
     201                 :            : 
     202                 :            :   // create interpolator (use cubic splines)
     203         [ #  # ]:          0 :   interpolator * inter = new interpolator ();
     204                 :          0 :   inter->rvectors (da, dt);
     205                 :          0 :   inter->prepare (INTERPOL_CUBIC, REPEAT_NO, DATA_RECTANGULAR);
     206                 :            : 
     207                 :            :   // adjust the time domain vector using interpolation
     208                 :          0 :   nr_double_t * ida = new nr_double_t[2 * nlen];
     209                 :          0 :   nr_double_t tstep = duration / (nlen - 1);
     210         [ #  # ]:          0 :   for (i = 0; i < nlen; i++) {
     211                 :          0 :     nr_double_t t = i * tstep + tstart;
     212                 :          0 :     ida[2 * i + 0] = inter->rinterpolate (t);
     213                 :          0 :     ida[2 * i + 1] = 0;
     214                 :            :   }
     215                 :            : 
     216                 :            :   // destroy interpolator
     217         [ #  # ]:          0 :   delete inter;
     218                 :            : 
     219                 :            :   // run actual EMI receiver computations
     220                 :          0 :   vector * res = receiver (ida, duration, nlen);
     221                 :            : 
     222                 :            :   // delete intermediate data
     223         [ #  # ]:          0 :   delete[] ida;
     224                 :            : 
     225                 :          0 :   return res;
     226                 :            : }
     227                 :            : 
     228                 :            : } // namespace qucs

Generated by: LCOV version 1.11