Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:54 2009

## Asterisk developer's documentation

- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- Directories

# fskmodem.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 1999 - 2005, Digium, Inc.
    00005  *
    00006  * Mark Spencer <markster@digium.com>
    00007  *
    00008  * Includes code and algorithms from the Zapata library.
    00009  *
    00010  * See http://www.asterisk.org for more information about
    00011  * the Asterisk project. Please do not directly contact
    00012  * any of the maintainers of this project for assistance;
    00013  * the project provides a web site, mailing lists and IRC
    00014  * channels for your use.
    00015  *
    00016  * This program is free software, distributed under the terms of
    00017  * the GNU General Public License Version 2. See the LICENSE file
    00018  * at the top of the source tree.
    00019  */
    00020
    00021 /*! \file
    00022  *
    00023  * \brief FSK Modulator/Demodulator
    00024  *
    00025  */
    00026
    00027 #include <stdio.h>
    00028
    00029 #include "asterisk.h"
    00030
    00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 77942 $")
    00032
    00033 #include "asterisk/fskmodem.h"
    00034
    00035 #define NBW 2
    00036 #define BWLIST {75,800}
    00037 #define  NF 6
    00038 #define  FLIST {1400,1800,1200,2200,1300,2100}
    00039
    00040 #define STATE_SEARCH_STARTBIT 0
    00041 #define STATE_SEARCH_STARTBIT2   1
    00042 #define STATE_SEARCH_STARTBIT3   2
    00043 #define STATE_GET_BYTE        3
    00044
    00045 static inline float get_sample(short **buffer, int *len)
    00046 {
    00047    float retval;
    00048    retval = (float) **buffer / 256;
    00049    (*buffer)++;
    00050    (*len)--;
    00051    return retval;
    00052 }
    00053
    00054 #define GET_SAMPLE get_sample(&buffer, len)
    00055
    00056 /* Coeficientes para filtros de entrada               */
    00057 /* Tabla de coeficientes, generada a partir del programa "mkfilter"  */
    00058 /* Formato: coef[IDX_FREC][IDX_BW][IDX_COEF]          */
    00059 /* IDX_COEF=0  => 1/GAIN                  */
    00060 /* IDX_COEF=1-6   => Coeficientes y[n]          */
    00061
    00062 static double coef_in[NF][NBW][8]={
    00063 #include "coef_in.h"
    00064 };
    00065
    00066 /* Coeficientes para filtro de salida              */
    00067 /* Tabla de coeficientes, generada a partir del programa "mkfilter"  */
    00068 /* Formato: coef[IDX_BW][IDX_COEF]              */
    00069 /* IDX_COEF=0  => 1/GAIN                  */
    00070 /* IDX_COEF=1-6   => Coeficientes y[n]          */
    00071
    00072 static double coef_out[NBW][8]={
    00073 #include "coef_out.h"
    00074 };
    00075
    00076
    00077 /*! Filtro pasa-banda para frecuencia de MARCA */
    00078 static inline float filtroM(fsk_data *fskd,float in)
    00079 {
    00080    int i,j;
    00081    double s;
    00082    double *pc;
    00083
    00084    pc=&coef_in[fskd->f_mark_idx][fskd->bw][0];
    00085    fskd->fmxv[(fskd->fmp+6)&7]=in*(*pc++);
    00086
    00087    s=(fskd->fmxv[(fskd->fmp+6)&7] - fskd->fmxv[fskd->fmp]) + 3 * (fskd->fmxv[(fskd->fmp+2)&7] - fskd->fmxv[(fskd->fmp+4)&7]);
    00088    for (i=0,j=fskd->fmp;i<6;i++,j++) s+=fskd->fmyv[j&7]*(*pc++);
    00089    fskd->fmyv[j&7]=s;
    00090    fskd->fmp++; fskd->fmp&=7;
    00091    return s;
    00092 }
    00093
    00094 /*! Filtro pasa-banda para frecuencia de ESPACIO */
    00095 static inline float filtroS(fsk_data *fskd,float in)
    00096 {
    00097    int i,j;
    00098    double s;
    00099    double *pc;
    00100
    00101    pc=&coef_in[fskd->f_space_idx][fskd->bw][0];
    00102    fskd->fsxv[(fskd->fsp+6)&7]=in*(*pc++);
    00103
    00104    s=(fskd->fsxv[(fskd->fsp+6)&7] - fskd->fsxv[fskd->fsp]) + 3 * (fskd->fsxv[(fskd->fsp+2)&7] - fskd->fsxv[(fskd->fsp+4)&7]);
    00105    for (i=0,j=fskd->fsp;i<6;i++,j++) s+=fskd->fsyv[j&7]*(*pc++);
    00106    fskd->fsyv[j&7]=s;
    00107    fskd->fsp++; fskd->fsp&=7;
    00108    return s;
    00109 }
    00110
    00111 /*! Filtro pasa-bajos para datos demodulados */
    00112 static inline float filtroL(fsk_data *fskd,float in)
    00113 {
    00114    int i,j;
    00115    double s;
    00116    double *pc;
    00117
    00118    pc=&coef_out[fskd->bw][0];
    00119    fskd->flxv[(fskd->flp + 6) & 7]=in * (*pc++);
    00120
    00121    s=     (fskd->flxv[fskd->flp]       + fskd->flxv[(fskd->flp+6)&7]) +
    00122      6  * (fskd->flxv[(fskd->flp+1)&7] + fskd->flxv[(fskd->flp+5)&7]) +
    00123      15 * (fskd->flxv[(fskd->flp+2)&7] + fskd->flxv[(fskd->flp+4)&7]) +
    00124      20 *  fskd->flxv[(fskd->flp+3)&7];
    00125
    00126    for (i=0,j=fskd->flp;i<6;i++,j++) s+=fskd->flyv[j&7]*(*pc++);
    00127    fskd->flyv[j&7]=s;
    00128    fskd->flp++; fskd->flp&=7;
    00129    return s;
    00130 }
    00131
    00132 static inline int demodulador(fsk_data *fskd, float *retval, float x)
    00133 {
    00134    float xS,xM;
    00135
    00136    fskd->cola_in[fskd->pcola]=x;
    00137
    00138    xS=filtroS(fskd,x);
    00139    xM=filtroM(fskd,x);
    00140
    00141    fskd->cola_filtro[fskd->pcola]=xM-xS;
    00142
    00143    x=filtroL(fskd,xM*xM - xS*xS);
    00144
    00145    fskd->cola_demod[fskd->pcola++]=x;
    00146    fskd->pcola &= (NCOLA-1);
    00147
    00148    *retval = x;
    00149    return(0);
    00150 }
    00151
    00152 static int get_bit_raw(fsk_data *fskd, short *buffer, int *len)
    00153 {
    00154    /* Esta funcion implementa un DPLL para sincronizarse con los bits */
    00155    float x,spb,spb2,ds;
    00156    int f;
    00157
    00158    spb=fskd->spb;
    00159    if (fskd->spb == 7) spb = 8000.0 / 1200.0;
    00160    ds=spb/32.;
    00161    spb2=spb/2.;
    00162
    00163    for (f=0;;){
    00164       if (demodulador(fskd,&x, GET_SAMPLE)) return(-1);
    00165       if ((x*fskd->x0)<0) {   /* Transicion */
    00166          if (!f) {
    00167             if (fskd->cont<(spb2)) fskd->cont+=ds; else fskd->cont-=ds;
    00168             f=1;
    00169          }
    00170       }
    00171       fskd->x0=x;
    00172       fskd->cont+=1.;
    00173       if (fskd->cont>spb) {
    00174          fskd->cont-=spb;
    00175          break;
    00176       }
    00177    }
    00178    f=(x>0)?0x80:0;
    00179    return(f);
    00180 }
    00181
    00182 int fsk_serie(fsk_data *fskd, short *buffer, int *len, int *outbyte)
    00183 {
    00184    int a;
    00185    int i,j,n1,r;
    00186    int samples=0;
    00187    int olen;
    00188    int beginlen=*len;
    00189    int beginlenx;
    00190
    00191    switch(fskd->state) {
    00192       /* Pick up where we left off */
    00193    case STATE_SEARCH_STARTBIT2:
    00194       goto search_startbit2;
    00195    case STATE_SEARCH_STARTBIT3:
    00196       goto search_startbit3;
    00197    case STATE_GET_BYTE:
    00198       goto getbyte;
    00199    }
    00200    /* Esperamos bit de start  */
    00201    do {
    00202 /* this was jesus's nice, reasonable, working (at least with RTTY) code
    00203 to look for the beginning of the start bit. Unfortunately, since TTY/TDD's
    00204 just start sending a start bit with nothing preceding it at the beginning
    00205 of a transmission (what a LOSING design), we cant do it this elegantly */
    00206 /*
    00207       if (demodulador(zap,&x1)) return(-1);
    00208       for(;;) {
    00209          if (demodulador(zap,&x2)) return(-1);
    00210          if (x1>0 && x2<0) break;
    00211          x1=x2;
    00212       }
    00213 */
    00214 /* this is now the imprecise, losing, but functional code to detect the
    00215 beginning of a start bit in the TDD sceanario. It just looks for sufficient
    00216 level to maybe, perhaps, guess, maybe that its maybe the beginning of
    00217 a start bit, perhaps. This whole thing stinks! */
    00218       beginlenx=beginlen; /* just to avoid unused war warnings */
    00219       if (demodulador(fskd,&fskd->x1,GET_SAMPLE)) return(-1);
    00220       samples++;
    00221       for(;;)
    00222          {
    00223 search_startbit2:
    00224          if (*len <= 0) {
    00225             fskd->state = STATE_SEARCH_STARTBIT2;
    00226             return 0;
    00227          }
    00228          samples++;
    00229          if (demodulador(fskd,&fskd->x2,GET_SAMPLE)) return(-1);
    00230 #if 0
    00231          printf("x2 = %5.5f ", fskd->x2);
    00232 #endif
    00233          if (fskd->x2 < -0.5) break;
    00234          }
    00235 search_startbit3:
    00236       /* Esperamos 0.5 bits antes de usar DPLL */
    00237       i=fskd->spb/2;
    00238       if (*len < i) {
    00239          fskd->state = STATE_SEARCH_STARTBIT3;
    00240          return 0;
    00241       }
    00242       for(;i>0;i--) { if (demodulador(fskd,&fskd->x1,GET_SAMPLE)) return(-1);
    00243 #if 0
    00244          printf("x1 = %5.5f ", fskd->x1);
    00245 #endif
    00246    samples++; }
    00247
    00248       /* x1 debe ser negativo (confirmación del bit de start) */
    00249
    00250    } while (fskd->x1>0);
    00251    fskd->state = STATE_GET_BYTE;
    00252
    00253 getbyte:
    00254
    00255    /* Need at least 80 samples (for 1200) or
    00256       1320 (for 45.5) to be sure we'll have a byte */
    00257    if (fskd->nbit < 8) {
    00258       if (*len < 1320)
    00259          return 0;
    00260    } else {
    00261       if (*len < 80)
    00262          return 0;
    00263    }
    00264    /* Leemos ahora los bits de datos */
    00265    j=fskd->nbit;
    00266    for (a=n1=0;j;j--) {
    00267       olen = *len;
    00268       i=get_bit_raw(fskd, buffer, len);
    00269       buffer += (olen - *len);
    00270       if (i == -1) return(-1);
    00271       if (i) n1++;
    00272       a>>=1; a|=i;
    00273    }
    00274    j=8-fskd->nbit;
    00275    a>>=j;
    00276
    00277    /* Leemos bit de paridad (si existe) y la comprobamos */
    00278    if (fskd->paridad) {
    00279       olen = *len;
    00280       i=get_bit_raw(fskd, buffer, len);
    00281       buffer += (olen - *len);
    00282       if (i == -1) return(-1);
    00283       if (i) n1++;
    00284       if (fskd->paridad==1) { /* paridad=1 (par) */
    00285          if (n1&1) a|=0x100;     /* error */
    00286       } else {       /* paridad=2 (impar) */
    00287          if (!(n1&1)) a|=0x100;  /* error */
    00288       }
    00289    }
    00290
    00291    /* Leemos bits de STOP. Todos deben ser 1 */
    00292
    00293    for (j=fskd->nstop;j;j--) {
    00294       r = get_bit_raw(fskd, buffer, len);
    00295       if (r == -1) return(-1);
    00296       if (!r) a|=0x200;
    00297    }
    00298
    00299    /* Por fin retornamos  */
    00300    /* Bit 8 : Error de paridad */
    00301    /* Bit 9 : Error de Framming */
    00302
    00303    *outbyte = a;
    00304    fskd->state = STATE_SEARCH_STARTBIT;
    00305    return 1;
    00306 }