Logo Search packages:      
Sourcecode: hf version File versions

fskinlines.h

/*****************************************************************************/

/*
 *      fskinlines.h  --  binary FSK modem code, utility inline functions.
 *
 *      Copyright (C) 1997  Thomas Sailer (sailer@ife.ee.ethz.ch)
 *        Swiss Federal Institute of Technology (ETH), Electronics Lab
 *    
 *    modified by GŁnther Montag dl4mge
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *
 */

/*****************************************************************************/
#ifndef _FSKINLINES_H
#define _FSKINLINES_H


int brake = 0;
static unsigned short random_seed;

extern void errprintf(int severity, const char *fmt, ...);

extern __inline__ unsigned short random_num(void)
{
        random_seed = 28629 * random_seed + 157;
        return random_seed;
}

/* --------------------------------------------------------------------- */
/*
 * correlator cache routines
 */

extern __inline__ void cc_lock(unsigned int u)
{
      if (u >= CORRELATOR_CACHE)
            return;
      corr_cache[u].refcnt++;
}

extern __inline__ void cc_unlock(unsigned int u)
{
      if (u >= CORRELATOR_CACHE)
            return;
      if ((--corr_cache[u].refcnt) <= 0) {
            unsigned int i;

            for (i = 0; i < CORRELATOR_CACHE; i++) 
                  if (corr_cache[i].lru < 32767)
                        corr_cache[i].lru++;
            corr_cache[u].lru = 0;
            corr_cache[u].refcnt = 0;
      }
}

/* --------------------------------------------------------------------- */

extern __inline__ unsigned int cc_lookup
    (unsigned short phinc0, unsigned short phinc1)
{
      unsigned int j;

      /* find correlator cache entry */
      for (j = 0; j < CORRELATOR_CACHE; j++) 
            if (corr_cache[j].phase_incs[0] == phinc0 &&
                corr_cache[j].phase_incs[1] == phinc1)
                  return j;
      return ~0;
}

/* --------------------------------------------------------------------- */

extern __inline__ unsigned int cc_replace(void)
{
      unsigned int j, k = CORRELATOR_CACHE;
      int l = -1;

      for (j = 0; j < CORRELATOR_CACHE; j++)
            if (corr_cache[j].refcnt <= 0 && corr_cache[j].lru > l) {
                  k = j;
                  l = corr_cache[j].lru;
            }
      if (k < CORRELATOR_CACHE)
            return k;
      errprintf(SEV_WARNING, 
          "modem: out of filter coefficient cache entries\n");
      return random_num() % CORRELATOR_CACHE;
}

/* --------------------------------------------------------------------- */

extern __inline__ int isimplecos(unsigned int arg)
{
      return isintab[((arg+0x4000) >> (16-SINTABBITS)) & (SINTABSIZE-1)];
}

/* --------------------------------------------------------------------- */

extern __inline__ int isimplesin(unsigned int arg)
{
      return isintab[(arg >> (16-SINTABBITS)) & (SINTABSIZE-1)];
}

/* --------------------------------------------------------------------- */

extern __inline__ int itblcos(unsigned int arg)
{
      unsigned int x;
      int dx;
      int s, c;

      x = (arg + (0x8000 >> SINTABBITS)) & 
          (0xffffu & (0xffffu << (16-SINTABBITS)));
      dx = arg - x;
      x >>= (16-SINTABBITS);
      c = isintab[x+(0x4000 >> (16-SINTABBITS))];
      s = isintab[x];
      return c - ((s * dx * (int)(M_PI*64.0)) >> 21);
}

/* --------------------------------------------------------------------- */

extern __inline__ void itblcossin(unsigned int arg, int *cos, int *sin)
{
      unsigned int x;
      int dx;
      int s, c;

      x = (arg + (0x8000 >> SINTABBITS)) & 
          (0xffffu & (0xffffu << (16-SINTABBITS)));
      dx = arg - x;
      x >>= (16-SINTABBITS);
      c = isintab[x+(0x4000 >> (16-SINTABBITS))];
      s = isintab[x];
      *cos = c - ((s * dx * (int)(M_PI*64.0)) >> 21);
      *sin = s + ((c * dx * (int)(M_PI*64.0)) >> 21);
}

/* --------------------------------------------------------------------- */

#ifdef MODEM_FLOAT

extern __inline__ float fcorr(int n, const float *coeff, const short *inp)
{
      float sum = 0;
      int i;

      for (i = n; i > 0; i--, coeff++, inp--)
            sum += (*coeff) * (*inp);
      return sum;
}

/* --------------------------------------------------------------------- */

extern __inline__ float fsqr(float x) __attribute__ ((const));

extern __inline__ float fsqr(float x)
{
      return x*x;
}

/* --------------------------------------------------------------------- */

extern __inline__ l1_soft_t do_filter(struct l1rxslots *slot, short *s)
{
      unsigned int cc = slot->corr_cache;

      if (cc >= CORRELATOR_CACHE) {
            printf("do_filter: correlator cache index overrange\n");
            return 0;
      }
      return (fsqr(fcorr(slot->corrlen, corr_cache[cc].correlator[1][0], s)) +
            fsqr(fcorr(slot->corrlen, corr_cache[cc].correlator[1][1], s)) -
            fsqr(fcorr(slot->corrlen, corr_cache[cc].correlator[0][0], s)) -
            fsqr(fcorr(slot->corrlen, corr_cache[cc].correlator[0][1], s))) 
            * slot->scale;
}

/* --------------------------------------------------------------------- */

extern __inline__ float ftblcos(unsigned int arg)
{
      unsigned int x;
      int dx;
      float s, c;

      x = (arg + (0x8000 >> SINTABBITS)) & 
          (0xffffu & (0xffffu << (16-SINTABBITS)));
      dx = arg - x;
      x >>= (16-SINTABBITS);
      c = fsintab[x+(0x4000 >> (16-SINTABBITS))];
      s = fsintab[x];
      return c - s * (float)(M_PI/32768.0) * dx;
}

/* --------------------------------------------------------------------- */

extern __inline__ void ftblcossin(unsigned int arg, float *cos, float *sin)
{
      unsigned int x;
      int dx;
      float s, c;

      x = (arg + (0x8000 >> SINTABBITS)) & 
          (0xffffu & (0xffffu << (16-SINTABBITS)));
      dx = arg - x;
      x >>= (16-SINTABBITS);
      c = fsintab[x+(0x4000 >> (16-SINTABBITS))];
      s = fsintab[x];
      *cos = c - s * (float)(M_PI/32768.0) * dx;
      *sin = s + c * (float)(M_PI/32768.0) * dx;
}

/* --------------------------------------------------------------------- */

static void cc_prepare
    (struct l1rxslots *slot, unsigned short phinc0, unsigned short phinc1)
{
      unsigned int j, k, l, ph, phinc;

      slot->scale = 1.0/32768.0/fsqr(slot->corrlen);

      j = cc_lookup(phinc0, phinc1);
      if (j >= CORRELATOR_CACHE) {
          j = cc_replace();
          /* calculate the correlator values */
          printf("corr cache calc: %u  phases: 0x%04x 0x%04x\n", 
            j, phinc0, phinc1);
          corr_cache[j].phase_incs[0] = phinc0;
          corr_cache[j].phase_incs[1] = phinc1;
          for (k = 0; k < 2; k++) {
            phinc = corr_cache[j].phase_incs[k];
            for (ph = l = 0; 
                 l < L1CORR_LEN; 
                 l++, ph = (ph + phinc) & 0xffff)
                  ftblcossin
                      (ph, 
                      &corr_cache[j].correlator[k][0][l],
                      &corr_cache[j].correlator[k][1][l]);
            }
            corr_cache[j].valid = 1;
            corr_cache[j].refcnt = 0;
      }
      slot->corr_cache = j;
      cc_lock(j);
}

/* --------------------------------------------------------------------- */

#else /* MODEM_FLOAT */

#define SH1  8     /* min. ceil(log2(L1CORR_LEN)) - (31-(2*15-1)) */
#define SH2  (3*15-2*SH1)

#ifdef __i386__

extern __inline__ int icorr(int n, const int *coeff, const short *inp)
{
      int ret, rethi, tmp1 = 0, tmp2 = 0;

      __asm__("\n1:\n\t"
            "movswl (%0),%%eax\n\t"
            "imull (%1)\n\t"
            "subl $2,%0\n\t"
            "addl $4,%1\n\t"
            "addl %%eax,%3\n\t"
            "adcl %%edx,%4\n\t"
            "decl %2\n\t"
            "jne 1b\n\t"
            : "=&S" (inp), "=&D" (coeff), "=&c" (n), "=m" (tmp1), "=m" (tmp2)
            : "0" (inp), "1" (coeff), "2" (n)
            : "ax", "dx");
      __asm__("shrdl %2,%1,%0\n\t"
            "# sarl %2,%1\n\t"
            : "=&r" (ret), "=&r" (rethi)
            : "i" (SH1), "0" (tmp1), "1" (tmp2));


      return ret;
}

#else /* __i386__ */

extern __inline__ int icorr(int n, const int *coeff, const short *inp)
{
      long long sum = 0;
      int i;

      for (i = n; i > 0; i--, coeff++, inp--)
            sum += (*coeff) * (*inp);
      sum >>= SH1;
      return sum;
}

#endif /* __i386__ */

/* --------------------------------------------------------------------- */

extern __inline__ long long isqr(int x) __attribute__ ((const));

extern __inline__ long long isqr(int x)
{
      return ((long long)x) * ((long long)x);
}

/* --------------------------------------------------------------------- */

extern __inline__ l1_soft_t do_filter(struct l1rxslots *slot, short *s)
{
      
      unsigned int cc = slot->corr_cache;
        long long ll;
        int ret;
      
    static unsigned cnt = 0;

      if (cc >= CORRELATOR_CACHE) {
            printf("do_filter: correlator cache index overrange\n");
            return 0;
      }
      ll = isqr(icorr(slot->corrlen, corr_cache[cc].correlator[1][0], s)) +
            isqr(icorr(slot->corrlen, corr_cache[cc].correlator[1][1], s)) -
            isqr(icorr(slot->corrlen, corr_cache[cc].correlator[0][0], s)) -
            isqr(icorr(slot->corrlen, corr_cache[cc].correlator[0][1], s));
      ll >>= SH2;
      ret = (ll * slot->scale) >> 23;

      cnt++;
      cnt %= 512;
      if (!cnt){
            printf("corrout: %6d  intermediate: %Ld\n", ret, ll);
            if (brake > 0) {
                printf("xrun count reset: %d -> 0", brake); 
                brake = 0;
            }
      }
            return ret;
}

/* --------------------------------------------------------------------- */

static void cc_prepare
    (struct l1rxslots *slot, unsigned short phinc0, unsigned short phinc1)
{
      unsigned int j, k, l, ph, phinc;

      slot->scale = (1<<23) / (slot->corrlen*slot->corrlen);

      j = cc_lookup(phinc0, phinc1);
      if (j >= CORRELATOR_CACHE) {
          j = cc_replace();
          /* calculate the correlator values */
          printf("corr cache calc: %u  phases: 0x%04x 0x%04x\n", 
            j, phinc0, phinc1);
          corr_cache[j].phase_incs[0] = phinc0;
          corr_cache[j].phase_incs[1] = phinc1;
          for (k = 0; k < 2; k++) {
            phinc = corr_cache[j].phase_incs[k];
            for (ph = l = 0; l < L1CORR_LEN; l++, ph = (ph + phinc) & 0xffff)
                itblcossin(
                  ph, 
                  &corr_cache[j].correlator[k][0][l],
                  &corr_cache[j].correlator[k][1][l]);
            }
            corr_cache[j].refcnt = 0;
#if 0
            printk("corr: %u ph: 0x%04x 0x%04x\n", 
                j, corr_cache[j].phase_incs[0], 
                corr_cache[j].phase_incs[1]);
            for (l = 0; l < MAXCORRLEN; l++)
                printf("corr: %6d %6d %6d %6d\n", 
                  corr_cache[j].correlator[0][0][l],
                  corr_cache[j].correlator[0][1][l], 
                  corr_cache[j].correlator[1][0][l],
                  corr_cache[j].correlator[1][1][l]);
#endif
      }
      slot->corr_cache = j;
      cc_lock(j);
}

#endif /* MODEM_FLOAT */
/* --------------------------------------------------------------------- */
#endif  /* _FSKINLINES_H */

Generated by  Doxygen 1.6.0   Back to index