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