2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * Includes code and algorithms from the Zapata library.
10 * See http://www.asterisk.org for more information about
11 * the Asterisk project. Please do not directly contact
12 * any of the maintainers of this project for assistance;
13 * the project provides a web site, mailing lists and IRC
14 * channels for your use.
16 * This program is free software, distributed under the terms of
17 * the GNU General Public License Version 2. See the LICENSE file
18 * at the top of the source tree.
23 * \brief FSK Modulator/Demodulator
25 * \author Mark Spencer <markster@digium.com>
27 * \arg Includes code and algorithms from the Zapata library.
32 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
36 #include "asterisk/fskmodem.h"
39 #define BWLIST {75,800}
41 #define FLIST {1400,1800,1200,2200,1300,2100}
43 #define STATE_SEARCH_STARTBIT 0
44 #define STATE_SEARCH_STARTBIT2 1
45 #define STATE_SEARCH_STARTBIT3 2
46 #define STATE_GET_BYTE 3
48 static inline float get_sample(short **buffer
, int *len
)
51 retval
= (float) **buffer
/ 256;
57 #define GET_SAMPLE get_sample(&buffer, len)
59 /* Coeficientes para filtros de entrada */
60 /* Tabla de coeficientes, generada a partir del programa "mkfilter" */
61 /* Formato: coef[IDX_FREC][IDX_BW][IDX_COEF] */
62 /* IDX_COEF=0 => 1/GAIN */
63 /* IDX_COEF=1-6 => Coeficientes y[n] */
65 static double coef_in
[NF
][NBW
][8]={
69 /* Coeficientes para filtro de salida */
70 /* Tabla de coeficientes, generada a partir del programa "mkfilter" */
71 /* Formato: coef[IDX_BW][IDX_COEF] */
72 /* IDX_COEF=0 => 1/GAIN */
73 /* IDX_COEF=1-6 => Coeficientes y[n] */
75 static double coef_out
[NBW
][8]={
80 /*! Filtro pasa-banda para frecuencia de MARCA */
81 static inline float filtroM(fsk_data
*fskd
,float in
)
87 pc
=&coef_in
[fskd
->f_mark_idx
][fskd
->bw
][0];
88 fskd
->fmxv
[(fskd
->fmp
+6)&7]=in
*(*pc
++);
90 s
=(fskd
->fmxv
[(fskd
->fmp
+6)&7] - fskd
->fmxv
[fskd
->fmp
]) + 3 * (fskd
->fmxv
[(fskd
->fmp
+2)&7] - fskd
->fmxv
[(fskd
->fmp
+4)&7]);
91 for (i
=0,j
=fskd
->fmp
;i
<6;i
++,j
++) s
+=fskd
->fmyv
[j
&7]*(*pc
++);
93 fskd
->fmp
++; fskd
->fmp
&=7;
97 /*! Filtro pasa-banda para frecuencia de ESPACIO */
98 static inline float filtroS(fsk_data
*fskd
,float in
)
104 pc
=&coef_in
[fskd
->f_space_idx
][fskd
->bw
][0];
105 fskd
->fsxv
[(fskd
->fsp
+6)&7]=in
*(*pc
++);
107 s
=(fskd
->fsxv
[(fskd
->fsp
+6)&7] - fskd
->fsxv
[fskd
->fsp
]) + 3 * (fskd
->fsxv
[(fskd
->fsp
+2)&7] - fskd
->fsxv
[(fskd
->fsp
+4)&7]);
108 for (i
=0,j
=fskd
->fsp
;i
<6;i
++,j
++) s
+=fskd
->fsyv
[j
&7]*(*pc
++);
110 fskd
->fsp
++; fskd
->fsp
&=7;
114 /*! Filtro pasa-bajos para datos demodulados */
115 static inline float filtroL(fsk_data
*fskd
,float in
)
121 pc
=&coef_out
[fskd
->bw
][0];
122 fskd
->flxv
[(fskd
->flp
+ 6) & 7]=in
* (*pc
++);
124 s
= (fskd
->flxv
[fskd
->flp
] + fskd
->flxv
[(fskd
->flp
+6)&7]) +
125 6 * (fskd
->flxv
[(fskd
->flp
+1)&7] + fskd
->flxv
[(fskd
->flp
+5)&7]) +
126 15 * (fskd
->flxv
[(fskd
->flp
+2)&7] + fskd
->flxv
[(fskd
->flp
+4)&7]) +
127 20 * fskd
->flxv
[(fskd
->flp
+3)&7];
129 for (i
=0,j
=fskd
->flp
;i
<6;i
++,j
++) s
+=fskd
->flyv
[j
&7]*(*pc
++);
131 fskd
->flp
++; fskd
->flp
&=7;
135 static inline int demodulador(fsk_data
*fskd
, float *retval
, float x
)
139 fskd
->cola_in
[fskd
->pcola
]=x
;
144 fskd
->cola_filtro
[fskd
->pcola
]=xM
-xS
;
146 x
=filtroL(fskd
,xM
*xM
- xS
*xS
);
148 fskd
->cola_demod
[fskd
->pcola
++]=x
;
149 fskd
->pcola
&= (NCOLA
-1);
155 static int get_bit_raw(fsk_data
*fskd
, short *buffer
, int *len
)
157 /* Esta funcion implementa un DPLL para sincronizarse con los bits */
162 if (fskd
->spb
== 7) spb
= 8000.0 / 1200.0;
167 if (demodulador(fskd
,&x
, GET_SAMPLE
)) return(-1);
168 if ((x
*fskd
->x0
)<0) { /* Transicion */
170 if (fskd
->cont
<(spb2
)) fskd
->cont
+=ds
; else fskd
->cont
-=ds
;
176 if (fskd
->cont
>spb
) {
185 int fsk_serie(fsk_data
*fskd
, short *buffer
, int *len
, int *outbyte
)
191 switch(fskd
->state
) {
192 /* Pick up where we left off */
193 case STATE_SEARCH_STARTBIT2
:
194 goto search_startbit2
;
195 case STATE_SEARCH_STARTBIT3
:
196 goto search_startbit3
;
200 /* Esperamos bit de start */
202 /* this was jesus's nice, reasonable, working (at least with RTTY) code
203 to look for the beginning of the start bit. Unfortunately, since TTY/TDD's
204 just start sending a start bit with nothing preceding it at the beginning
205 of a transmission (what a LOSING design), we cant do it this elegantly */
207 if (demodulador(zap,&x1)) return(-1);
209 if (demodulador(zap,&x2)) return(-1);
210 if (x1>0 && x2<0) break;
214 /* this is now the imprecise, losing, but functional code to detect the
215 beginning of a start bit in the TDD sceanario. It just looks for sufficient
216 level to maybe, perhaps, guess, maybe that its maybe the beginning of
217 a start bit, perhaps. This whole thing stinks! */
218 if (demodulador(fskd
,&fskd
->x1
,GET_SAMPLE
)) return(-1);
224 fskd
->state
= STATE_SEARCH_STARTBIT2
;
228 if (demodulador(fskd
,&fskd
->x2
,GET_SAMPLE
)) return(-1);
230 printf("x2 = %5.5f ", fskd
->x2
);
232 if (fskd
->x2
< -0.5) break;
235 /* Esperamos 0.5 bits antes de usar DPLL */
238 fskd
->state
= STATE_SEARCH_STARTBIT3
;
241 for(;i
;i
--) { if (demodulador(fskd
,&fskd
->x1
,GET_SAMPLE
)) return(-1);
243 printf("x1 = %5.5f ", fskd
->x1
);
247 /* x1 debe ser negativo (confirmaciĆ³n del bit de start) */
249 } while (fskd
->x1
>0);
250 fskd
->state
= STATE_GET_BYTE
;
254 /* Need at least 80 samples (for 1200) or
255 1320 (for 45.5) to be sure we'll have a byte */
256 if (fskd
->nbit
< 8) {
263 /* Leemos ahora los bits de datos */
267 i
=get_bit_raw(fskd
, buffer
, len
);
268 buffer
+= (olen
- *len
);
269 if (i
== -1) return(-1);
276 /* Leemos bit de paridad (si existe) y la comprobamos */
279 i
=get_bit_raw(fskd
, buffer
, len
);
280 buffer
+= (olen
- *len
);
281 if (i
== -1) return(-1);
283 if (fskd
->paridad
==1) { /* paridad=1 (par) */
284 if (n1
&1) a
|=0x100; /* error */
285 } else { /* paridad=2 (impar) */
286 if (!(n1
&1)) a
|=0x100; /* error */
290 /* Leemos bits de STOP. Todos deben ser 1 */
292 for (j
=fskd
->nstop
;j
;j
--) {
293 r
= get_bit_raw(fskd
, buffer
, len
);
294 if (r
== -1) return(-1);
298 /* Por fin retornamos */
299 /* Bit 8 : Error de paridad */
300 /* Bit 9 : Error de Framming */
303 fskd
->state
= STATE_SEARCH_STARTBIT
;