1 /*
2 * selcall.c
3 *
4 * Copyright (C) 1996
5 * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu)
6 *
7 * Copyright (C) 2013
8 * Elias Oenal (EliasOenal@gmail.com)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 /* ---------------------------------------------------------------------- */
26
27 #include "multimon.h"
28 #include "filter.h"
29 #include <math.h>
30 #include <string.h>
31
32 /* ---------------------------------------------------------------------- */
33
34 #define SAMPLE_RATE 22050
35 #define BLOCKLEN (SAMPLE_RATE/100) /* 10ms blocks */
36 #define BLOCKNUM 4 /* must match numbers in multimon.h */
37 #define TIMEOUT_LIMIT 5 //50ms
38
selcall_init(struct demod_state * s)39 void selcall_init(struct demod_state *s)
40 {
41 memset(&s->l1.selcall, 0, sizeof(s->l1.selcall));
42 }
43
selcall_deinit(struct demod_state * s)44 void selcall_deinit(struct demod_state *s)
45 {
46 if(s->l1.selcall.timeout != 0)
47 verbprintf(0, "\n");
48 }
49
find_max_idx(const float * f)50 int find_max_idx(const float *f)
51 {
52 float en = 0;
53 int idx = -1, i;
54
55 for (i = 0; i < 16; i++)
56 if (f[i] > en) {
57 en = f[i];
58 idx = i;
59 }
60 if (idx < 0)
61 return -1;
62 en *= 0.1;
63 for (i = 0; i < 16; i++)
64 if (idx != i && f[i] > en)
65 return -1;
66 return idx;
67 }
68
process_block(struct demod_state * s)69 static inline int process_block(struct demod_state *s)
70 {
71 float tote;
72 float totte[32];
73 int i, j;
74
75 tote = 0;
76 for (i = 0; i < BLOCKNUM; i++)
77 tote += s->l1.selcall.energy[i];
78 for (i = 0; i < 32; i++) {
79 totte[i] = 0;
80 for (j = 0; j < BLOCKNUM; j++)
81 totte[i] += s->l1.selcall.tenergy[j][i];
82 }
83 for (i = 0; i < 16; i++)
84 totte[i] = fsqr(totte[i]) + fsqr(totte[i+16]);
85 memmove(s->l1.selcall.energy+1, s->l1.selcall.energy,
86 sizeof(s->l1.selcall.energy) - sizeof(s->l1.selcall.energy[0]));
87 s->l1.selcall.energy[0] = 0;
88 memmove(s->l1.selcall.tenergy+1, s->l1.selcall.tenergy,
89 sizeof(s->l1.selcall.tenergy) - sizeof(s->l1.selcall.tenergy[0]));
90 memset(s->l1.selcall.tenergy, 0, sizeof(s->l1.selcall.tenergy[0]));
91 tote *= (BLOCKNUM*BLOCKLEN*0.5); /* adjust for block lengths */
92 verbprintf(10, "selcall: Energies: %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f"
93 " %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f\n",
94 tote, totte[0], totte[1], totte[2], totte[3], totte[4], totte[5], totte[6], totte[7],
95 totte[8], totte[9], totte[10], totte[11], totte[12], totte[13], totte[14], totte[15]);
96 if ((i = find_max_idx(totte)) < 0)
97 return -1;
98 if ((tote * 0.4) > totte[i])
99 return -1;
100 return i;
101 }
102
selcall_demod(struct demod_state * s,const float * buffer,int length,const unsigned int * selcall_freq,const char * const name)103 void selcall_demod(struct demod_state *s, const float *buffer, int length,
104 const unsigned int *selcall_freq, const char * const name)
105 {
106 float s_in;
107 int i;
108
109 for (; length > 0; length--, buffer++) {
110 s_in = *buffer;
111 s->l1.selcall.energy[0] += fsqr(s_in);
112 for (i = 0; i < 16; i++) {
113 s->l1.selcall.tenergy[0][i] += COS(s->l1.selcall.ph[i]) * s_in;
114 s->l1.selcall.tenergy[0][i+16] += SIN(s->l1.selcall.ph[i]) * s_in;
115 s->l1.selcall.ph[i] += selcall_freq[i];
116 }
117 if ((s->l1.selcall.blkcount--) <= 0) {
118 s->l1.selcall.blkcount = BLOCKLEN;
119 i = process_block(s);
120 if (i != s->l1.selcall.lastch && i >= 0)
121 {
122 if(s->l1.selcall.timeout == 0)
123 verbprintf(0, "%s: ", name);
124 verbprintf(0, "%1X", i);
125 s->l1.selcall.timeout = 1;
126 }
127
128 if(i == -1 && s->l1.selcall.timeout != 0)
129 s->l1.selcall.timeout++;
130 if(s->l1.selcall.timeout > TIMEOUT_LIMIT+1)
131 {
132 verbprintf(0, "\n");
133 s->l1.selcall.timeout = 0;
134 }
135
136 s->l1.selcall.lastch = i;
137 }
138 }
139 }
140