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