Skip to content
Snippets Groups Projects
Commit 89e58f12 authored by Mark Spencer's avatar Mark Spencer
Browse files

Version 0.1.7 from FTP

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@255 65c4cc65-6c06-0410-ace0-fbb531ad65f3
parent cc1ca5d1
Branches
Tags
No related merge requests found
/*
* Asterisk -- A telephony toolkit for Linux.
*
* FSK Modulator/Demodulator
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License.
*
* Includes code and algorithms from the Zapata library.
*
*/
#include <asterisk/fskmodem.h>
#include <stdio.h>
#define NBW 2
#define BWLIST {75,800}
#define NF 4
#define FLIST {1400,1800,1200,2200}
#define STATE_SEARCH_STARTBIT 0
#define STATE_SEARCH_STARTBIT2 1
#define STATE_SEARCH_STARTBIT3 2
#define STATE_GET_BYTE 3
static inline float get_sample(short **buffer, int *len)
{
float retval;
retval = (float) **buffer / 256;
(*buffer)++;
(*len)--;
return retval;
}
#define GET_SAMPLE get_sample(&buffer, len)
/* Coeficientes para filtros de entrada */
/* Tabla de coeficientes, generada a partir del programa "mkfilter" */
/* Formato: coef[IDX_FREC][IDX_BW][IDX_COEF] */
/* IDX_COEF=0 => 1/GAIN */
/* IDX_COEF=1-6 => Coeficientes y[n] */
static double coef_in[NF][NBW][8]={
#include "coef_in.h"
};
/* Coeficientes para filtro de salida */
/* Tabla de coeficientes, generada a partir del programa "mkfilter" */
/* Formato: coef[IDX_BW][IDX_COEF] */
/* IDX_COEF=0 => 1/GAIN */
/* IDX_COEF=1-6 => Coeficientes y[n] */
static double coef_out[NBW][8]={
#include "coef_out.h"
};
/* Filtro pasa-banda para frecuencia de MARCA */
static inline float filtroM(fsk_data *fskd,float in)
{
int i,j;
double s;
double *pc;
pc=&coef_in[fskd->f_mark_idx][fskd->bw][0];
fskd->fmxv[(fskd->fmp+6)&7]=in*(*pc++);
s=(fskd->fmxv[(fskd->fmp+6)&7] - fskd->fmxv[fskd->fmp]) + 3 * (fskd->fmxv[(fskd->fmp+2)&7] - fskd->fmxv[(fskd->fmp+4)&7]);
for (i=0,j=fskd->fmp;i<6;i++,j++) s+=fskd->fmyv[j&7]*(*pc++);
fskd->fmyv[j&7]=s;
fskd->fmp++; fskd->fmp&=7;
return s;
}
/* Filtro pasa-banda para frecuencia de ESPACIO */
static inline float filtroS(fsk_data *fskd,float in)
{
int i,j;
double s;
double *pc;
pc=&coef_in[fskd->f_space_idx][fskd->bw][0];
fskd->fsxv[(fskd->fsp+6)&7]=in*(*pc++);
s=(fskd->fsxv[(fskd->fsp+6)&7] - fskd->fsxv[fskd->fsp]) + 3 * (fskd->fsxv[(fskd->fsp+2)&7] - fskd->fsxv[(fskd->fsp+4)&7]);
for (i=0,j=fskd->fsp;i<6;i++,j++) s+=fskd->fsyv[j&7]*(*pc++);
fskd->fsyv[j&7]=s;
fskd->fsp++; fskd->fsp&=7;
return s;
}
/* Filtro pasa-bajos para datos demodulados */
static inline float filtroL(fsk_data *fskd,float in)
{
int i,j;
double s;
double *pc;
pc=&coef_out[fskd->bw][0];
fskd->flxv[(fskd->flp + 6) & 7]=in * (*pc++);
s= (fskd->flxv[fskd->flp] + fskd->flxv[(fskd->flp+6)&7]) +
6 * (fskd->flxv[(fskd->flp+1)&7] + fskd->flxv[(fskd->flp+5)&7]) +
15 * (fskd->flxv[(fskd->flp+2)&7] + fskd->flxv[(fskd->flp+4)&7]) +
20 * fskd->flxv[(fskd->flp+3)&7];
for (i=0,j=fskd->flp;i<6;i++,j++) s+=fskd->flyv[j&7]*(*pc++);
fskd->flyv[j&7]=s;
fskd->flp++; fskd->flp&=7;
return s;
}
static inline int demodulador(fsk_data *fskd, float *retval, float x)
{
float xS,xM;
fskd->cola_in[fskd->pcola]=x;
xS=filtroS(fskd,x);
xM=filtroM(fskd,x);
fskd->cola_filtro[fskd->pcola]=xM-xS;
x=filtroL(fskd,xM*xM - xS*xS);
fskd->cola_demod[fskd->pcola++]=x;
fskd->pcola &= (NCOLA-1);
*retval = x;
return(0);
}
static int get_bit_raw(fsk_data *fskd, short *buffer, int *len)
{
/* Esta funcion implementa un DPLL para sincronizarse con los bits */
float x,spb,spb2,ds;
int f;
spb=fskd->spb;
if (fskd->spb == 7) spb = 8000.0 / 1200.0;
ds=spb/32.;
spb2=spb/2.;
for (f=0;;){
if (demodulador(fskd,&x, GET_SAMPLE)) return(-1);
if ((x*fskd->x0)<0) { /* Transicion */
if (!f) {
if (fskd->cont<(spb2)) fskd->cont+=ds; else fskd->cont-=ds;
f=1;
}
}
fskd->x0=x;
fskd->cont+=1.;
if (fskd->cont>spb) {
fskd->cont-=spb;
break;
}
}
f=(x>0)?0x80:0;
return(f);
}
int fsk_serie(fsk_data *fskd, short *buffer, int *len, int *outbyte)
{
int a;
int i,j,n1,r;
int samples=0;
int olen;
switch(fskd->state) {
/* Pick up where we left off */
case STATE_SEARCH_STARTBIT2:
goto search_startbit2;
case STATE_SEARCH_STARTBIT3:
goto search_startbit3;
case STATE_GET_BYTE:
goto getbyte;
}
/* Esperamos bit de start */
do {
/* this was jesus's nice, reasonable, working (at least with RTTY) code
to look for the beginning of the start bit. Unfortunately, since TTY/TDD's
just start sending a start bit with nothing preceding it at the beginning
of a transmission (what a LOSING design), we cant do it this elegantly */
/*
if (demodulador(zap,&x1)) return(-1);
for(;;) {
if (demodulador(zap,&x2)) return(-1);
if (x1>0 && x2<0) break;
x1=x2;
}
*/
/* this is now the imprecise, losing, but functional code to detect the
beginning of a start bit in the TDD sceanario. It just looks for sufficient
level to maybe, perhaps, guess, maybe that its maybe the beginning of
a start bit, perhaps. This whole thing stinks! */
if (demodulador(fskd,&fskd->x1,GET_SAMPLE)) return(-1);
samples++;
for(;;)
{
search_startbit2:
if (!*len) {
fskd->state = STATE_SEARCH_STARTBIT2;
return 0;
}
samples++;
if (demodulador(fskd,&fskd->x2,GET_SAMPLE)) return(-1);
#if 0
printf("x2 = %5.5f ", fskd->x2);
#endif
if (fskd->x2 < -0.5) break;
}
search_startbit3:
/* Esperamos 0.5 bits antes de usar DPLL */
i=fskd->spb/2;
if (*len < i) {
fskd->state = STATE_SEARCH_STARTBIT3;
return 0;
}
for(;i;i--) { if (demodulador(fskd,&fskd->x1,GET_SAMPLE)) return(-1);
#if 0
printf("x1 = %5.5f ", fskd->x1);
#endif
samples++; }
/* x1 debe ser negativo (confirmacin del bit de start) */
} while (fskd->x1>0);
fskd->state = STATE_GET_BYTE;
getbyte:
/* Need at least 80 samples to be sure we'll have a byte */
if (*len < 80)
return 0;
/* Leemos ahora los bits de datos */
j=fskd->nbit;
for (a=n1=0;j;j--) {
olen = *len;
i=get_bit_raw(fskd, buffer, len);
buffer += (olen - *len);
if (i == -1) return(-1);
if (i) n1++;
a>>=1; a|=i;
}
j=8-fskd->nbit;
a>>=j;
/* Leemos bit de paridad (si existe) y la comprobamos */
if (fskd->paridad) {
olen = *len;
i=get_bit_raw(fskd, buffer, len);
buffer += (olen - *len);
if (i == -1) return(-1);
if (i) n1++;
if (fskd->paridad==1) { /* paridad=1 (par) */
if (n1&1) a|=0x100; /* error */
} else { /* paridad=2 (impar) */
if (!(n1&1)) a|=0x100; /* error */
}
}
/* Leemos bits de STOP. Todos deben ser 1 */
for (j=fskd->nstop;j;j--) {
r = get_bit_raw(fskd, buffer, len);
if (r == -1) return(-1);
if (!r) a|=0x200;
}
/* Por fin retornamos */
/* Bit 8 : Error de paridad */
/* Bit 9 : Error de Framming */
*outbyte = a;
fskd->state = STATE_SEARCH_STARTBIT;
return 1;
}
/*
* Asterisk -- A telephony toolkit for Linux.
*
* FSK Modem Support
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License.
*
* Includes code and algorithms from the Zapata library.
*
*/
#ifndef _FSKMODEM_H
#define _FSKMODEM_H
#define PARITY_NONE 0
#define PARITY_EVEN 1
#define PARITY_ODD 2
#define NCOLA 0x4000
typedef struct {
float spb; /* Samples / Bit */
int nbit; /* Number of Data Bits (5,7,8) */
float nstop; /* Number of Stop Bits 1,1.5,2 */
int paridad; /* Parity 0=none 1=even 2=odd */
int hdlc; /* Modo Packet */
float x0;
float x1;
float x2;
float cont;
int bw; /* Ancho de Banda */
double fmxv[8],fmyv[8]; /* filter stuff for M filter */
int fmp; /* pointer for M filter */
double fsxv[8],fsyv[8]; /* filter stuff for S filter */
int fsp; /* pointer for S filter */
double flxv[8],flyv[8]; /* filter stuff for L filter */
int flp; /* pointer for L filter */
int f_mark_idx; /* Indice de frecuencia de marca (f_M-500)/5 */
int f_space_idx;/* Indice de frecuencia de espacio (f_S-500)/5 */
int state;
int pcola; /* Puntero de las colas de datos */
float cola_in[NCOLA]; /* Cola de muestras de entrada */
float cola_filtro[NCOLA]; /* Cola de muestras tras filtros */
float cola_demod[NCOLA]; /* Cola de muestras demoduladas */
} fsk_data;
/* Retrieve a serial byte into outbyte. Buffer is a pointer into a series of
shorts and len records the number of bytes in the buffer. len will be
overwritten with the number of bytes left that were not consumed, and the
return value is as follows:
0: Still looking for something...
1: An output byte was received and stored in outbyte
-1: An error occured in the transmission
He must be called with at least 80 bytes of buffer. */
extern int fsk_serie(fsk_data *fskd, short *buffer, int *len, int *outbyte);
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment