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