1 /*
2 * demod_clipfsk.c -- 1200 baud FSK demodulator
3 *
4 * Copyright (C) 2007
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /* ---------------------------------------------------------------------- */
22
23 #include "multimon.h"
24 #include "filter.h"
25 #include <math.h>
26 #include <string.h>
27
28 /* ---------------------------------------------------------------------- */
29
30 /*
31 * V.23 signaling 1200 baud +/- 1%
32 * Mark frequency: 2300 Hz +/- 1.5%
33 * Space frequency: 1100 Hz +/- 1.5%
34 */
35
36 #define FREQ_MARK 1200
37 #define FREQ_SPACE 2200
38 #define FREQ_SAMP 22050
39 #define BAUD 1200
40 #define SUBSAMP 2
41
42 /* ---------------------------------------------------------------------- */
43
44 #define CORRLEN ((int)(FREQ_SAMP/BAUD))
45 #define SPHASEINC (0x10000u*BAUD*SUBSAMP/FREQ_SAMP)
46
47 static float corr_mark_i[CORRLEN];
48 static float corr_mark_q[CORRLEN];
49 static float corr_space_i[CORRLEN];
50 static float corr_space_q[CORRLEN];
51
52 /* ---------------------------------------------------------------------- */
53
clipfsk_init(struct demod_state * s)54 static void clipfsk_init(struct demod_state *s)
55 {
56 float f;
57 int i;
58
59 clip_init(s);
60 memset(&s->l1.clipfsk, 0, sizeof(s->l1.clipfsk));
61 for (f = 0, i = 0; i < CORRLEN; i++) {
62 corr_mark_i[i] = cos(f);
63 corr_mark_q[i] = sin(f);
64 f += 2.0*M_PI*FREQ_MARK/FREQ_SAMP;
65 }
66 for (f = 0, i = 0; i < CORRLEN; i++) {
67 corr_space_i[i] = cos(f);
68 corr_space_q[i] = sin(f);
69 f += 2.0*M_PI*FREQ_SPACE/FREQ_SAMP;
70 }
71 }
72
73 /* ---------------------------------------------------------------------- */
74
clipfsk_demod(struct demod_state * s,buffer_t buffer,int length)75 static void clipfsk_demod(struct demod_state *s, buffer_t buffer, int length)
76 {
77 float f;
78 unsigned char curbit;
79
80 if (s->l1.clipfsk.subsamp) {
81 int numfill = SUBSAMP - s->l1.clipfsk.subsamp;
82 if (length < numfill) {
83 s->l1.clipfsk.subsamp += length;
84 return;
85 }
86 buffer.fbuffer += numfill;
87 length -= numfill;
88 s->l1.clipfsk.subsamp = 0;
89 }
90 for (; length >= SUBSAMP; length -= SUBSAMP, buffer.fbuffer += SUBSAMP) {
91 f = fsqr(mac(buffer.fbuffer, corr_mark_i, CORRLEN)) +
92 fsqr(mac(buffer.fbuffer, corr_mark_q, CORRLEN)) -
93 fsqr(mac(buffer.fbuffer, corr_space_i, CORRLEN)) -
94 fsqr(mac(buffer.fbuffer, corr_space_q, CORRLEN));
95 s->l1.clipfsk.dcd_shreg <<= 1;
96 s->l1.clipfsk.dcd_shreg |= (f > 0);
97 verbprintf(10, "%c", '0'+(s->l1.clipfsk.dcd_shreg & 1));
98 /*
99 * check if transition
100 */
101 if ((s->l1.clipfsk.dcd_shreg ^ (s->l1.clipfsk.dcd_shreg >> 1)) & 1) {
102 if (s->l1.clipfsk.sphase < (0x8000u-(SPHASEINC/2)))
103 s->l1.clipfsk.sphase += SPHASEINC/8;
104 else
105 s->l1.clipfsk.sphase -= SPHASEINC/8;
106 }
107 s->l1.clipfsk.sphase += SPHASEINC;
108 if (s->l1.clipfsk.sphase >= 0x10000u) {
109 s->l1.clipfsk.sphase &= 0xffffu;
110 curbit = s->l1.clipfsk.dcd_shreg & 1;
111 verbprintf(9, " %c ", '0'+curbit);
112 clip_rxbit(s, curbit);
113 }
114 }
115 s->l1.clipfsk.subsamp = length;
116 }
117
118 /* ---------------------------------------------------------------------- */
119
120 const struct demod_param demod_clipfsk = {
121 "CLIPFSK", true, FREQ_SAMP, CORRLEN, clipfsk_init, clipfsk_demod, NULL
122 };
123
124 /* ---------------------------------------------------------------------- */
125