Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/isdn/hardware/eicon/capidtmf.c
15115 views
1
2
/*
3
*
4
Copyright (c) Eicon Networks, 2002.
5
*
6
This source file is supplied for the use with
7
Eicon Networks range of DIVA Server Adapters.
8
*
9
Eicon File Revision : 2.1
10
*
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 2, or (at your option)
14
any later version.
15
*
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
See the GNU General Public License for more details.
20
*
21
You should have received a copy of the GNU General Public License
22
along with this program; if not, write to the Free Software
23
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
*
25
*/
26
27
#include "platform.h"
28
29
30
31
32
33
34
35
36
37
#include "capidtmf.h"
38
39
/* #define TRACE_ */
40
41
#define FILE_ "CAPIDTMF.C"
42
43
/*---------------------------------------------------------------------------*/
44
45
46
#define trace(a)
47
48
49
50
/*---------------------------------------------------------------------------*/
51
52
static short capidtmf_expand_table_alaw[0x0100] =
53
{
54
-5504, 5504, -344, 344, -22016, 22016, -1376, 1376,
55
-2752, 2752, -88, 88, -11008, 11008, -688, 688,
56
-7552, 7552, -472, 472, -30208, 30208, -1888, 1888,
57
-3776, 3776, -216, 216, -15104, 15104, -944, 944,
58
-4480, 4480, -280, 280, -17920, 17920, -1120, 1120,
59
-2240, 2240, -24, 24, -8960, 8960, -560, 560,
60
-6528, 6528, -408, 408, -26112, 26112, -1632, 1632,
61
-3264, 3264, -152, 152, -13056, 13056, -816, 816,
62
-6016, 6016, -376, 376, -24064, 24064, -1504, 1504,
63
-3008, 3008, -120, 120, -12032, 12032, -752, 752,
64
-8064, 8064, -504, 504, -32256, 32256, -2016, 2016,
65
-4032, 4032, -248, 248, -16128, 16128, -1008, 1008,
66
-4992, 4992, -312, 312, -19968, 19968, -1248, 1248,
67
-2496, 2496, -56, 56, -9984, 9984, -624, 624,
68
-7040, 7040, -440, 440, -28160, 28160, -1760, 1760,
69
-3520, 3520, -184, 184, -14080, 14080, -880, 880,
70
-5248, 5248, -328, 328, -20992, 20992, -1312, 1312,
71
-2624, 2624, -72, 72, -10496, 10496, -656, 656,
72
-7296, 7296, -456, 456, -29184, 29184, -1824, 1824,
73
-3648, 3648, -200, 200, -14592, 14592, -912, 912,
74
-4224, 4224, -264, 264, -16896, 16896, -1056, 1056,
75
-2112, 2112, -8, 8, -8448, 8448, -528, 528,
76
-6272, 6272, -392, 392, -25088, 25088, -1568, 1568,
77
-3136, 3136, -136, 136, -12544, 12544, -784, 784,
78
-5760, 5760, -360, 360, -23040, 23040, -1440, 1440,
79
-2880, 2880, -104, 104, -11520, 11520, -720, 720,
80
-7808, 7808, -488, 488, -31232, 31232, -1952, 1952,
81
-3904, 3904, -232, 232, -15616, 15616, -976, 976,
82
-4736, 4736, -296, 296, -18944, 18944, -1184, 1184,
83
-2368, 2368, -40, 40, -9472, 9472, -592, 592,
84
-6784, 6784, -424, 424, -27136, 27136, -1696, 1696,
85
-3392, 3392, -168, 168, -13568, 13568, -848, 848
86
};
87
88
static short capidtmf_expand_table_ulaw[0x0100] =
89
{
90
-32124, 32124, -1884, 1884, -7932, 7932, -372, 372,
91
-15996, 15996, -876, 876, -3900, 3900, -120, 120,
92
-23932, 23932, -1372, 1372, -5884, 5884, -244, 244,
93
-11900, 11900, -620, 620, -2876, 2876, -56, 56,
94
-28028, 28028, -1628, 1628, -6908, 6908, -308, 308,
95
-13948, 13948, -748, 748, -3388, 3388, -88, 88,
96
-19836, 19836, -1116, 1116, -4860, 4860, -180, 180,
97
-9852, 9852, -492, 492, -2364, 2364, -24, 24,
98
-30076, 30076, -1756, 1756, -7420, 7420, -340, 340,
99
-14972, 14972, -812, 812, -3644, 3644, -104, 104,
100
-21884, 21884, -1244, 1244, -5372, 5372, -212, 212,
101
-10876, 10876, -556, 556, -2620, 2620, -40, 40,
102
-25980, 25980, -1500, 1500, -6396, 6396, -276, 276,
103
-12924, 12924, -684, 684, -3132, 3132, -72, 72,
104
-17788, 17788, -988, 988, -4348, 4348, -148, 148,
105
-8828, 8828, -428, 428, -2108, 2108, -8, 8,
106
-31100, 31100, -1820, 1820, -7676, 7676, -356, 356,
107
-15484, 15484, -844, 844, -3772, 3772, -112, 112,
108
-22908, 22908, -1308, 1308, -5628, 5628, -228, 228,
109
-11388, 11388, -588, 588, -2748, 2748, -48, 48,
110
-27004, 27004, -1564, 1564, -6652, 6652, -292, 292,
111
-13436, 13436, -716, 716, -3260, 3260, -80, 80,
112
-18812, 18812, -1052, 1052, -4604, 4604, -164, 164,
113
-9340, 9340, -460, 460, -2236, 2236, -16, 16,
114
-29052, 29052, -1692, 1692, -7164, 7164, -324, 324,
115
-14460, 14460, -780, 780, -3516, 3516, -96, 96,
116
-20860, 20860, -1180, 1180, -5116, 5116, -196, 196,
117
-10364, 10364, -524, 524, -2492, 2492, -32, 32,
118
-24956, 24956, -1436, 1436, -6140, 6140, -260, 260,
119
-12412, 12412, -652, 652, -3004, 3004, -64, 64,
120
-16764, 16764, -924, 924, -4092, 4092, -132, 132,
121
-8316, 8316, -396, 396, -1980, 1980, 0, 0
122
};
123
124
125
/*---------------------------------------------------------------------------*/
126
127
static short capidtmf_recv_window_function[CAPIDTMF_RECV_ACCUMULATE_CYCLES] =
128
{
129
-500L, -999L, -1499L, -1998L, -2496L, -2994L, -3491L, -3988L,
130
-4483L, -4978L, -5471L, -5963L, -6454L, -6943L, -7431L, -7917L,
131
-8401L, -8883L, -9363L, -9840L, -10316L, -10789L, -11259L, -11727L,
132
-12193L, -12655L, -13115L, -13571L, -14024L, -14474L, -14921L, -15364L,
133
-15804L, -16240L, -16672L, -17100L, -17524L, -17944L, -18360L, -18772L,
134
-19180L, -19583L, -19981L, -20375L, -20764L, -21148L, -21527L, -21901L,
135
-22270L, -22634L, -22993L, -23346L, -23694L, -24037L, -24374L, -24705L,
136
-25030L, -25350L, -25664L, -25971L, -26273L, -26568L, -26858L, -27141L,
137
-27418L, -27688L, -27952L, -28210L, -28461L, -28705L, -28943L, -29174L,
138
-29398L, -29615L, -29826L, -30029L, -30226L, -30415L, -30598L, -30773L,
139
-30941L, -31102L, -31256L, -31402L, -31541L, -31673L, -31797L, -31914L,
140
-32024L, -32126L, -32221L, -32308L, -32388L, -32460L, -32524L, -32581L,
141
-32631L, -32673L, -32707L, -32734L, -32753L, -32764L, -32768L, -32764L,
142
-32753L, -32734L, -32707L, -32673L, -32631L, -32581L, -32524L, -32460L,
143
-32388L, -32308L, -32221L, -32126L, -32024L, -31914L, -31797L, -31673L,
144
-31541L, -31402L, -31256L, -31102L, -30941L, -30773L, -30598L, -30415L,
145
-30226L, -30029L, -29826L, -29615L, -29398L, -29174L, -28943L, -28705L,
146
-28461L, -28210L, -27952L, -27688L, -27418L, -27141L, -26858L, -26568L,
147
-26273L, -25971L, -25664L, -25350L, -25030L, -24705L, -24374L, -24037L,
148
-23694L, -23346L, -22993L, -22634L, -22270L, -21901L, -21527L, -21148L,
149
-20764L, -20375L, -19981L, -19583L, -19180L, -18772L, -18360L, -17944L,
150
-17524L, -17100L, -16672L, -16240L, -15804L, -15364L, -14921L, -14474L,
151
-14024L, -13571L, -13115L, -12655L, -12193L, -11727L, -11259L, -10789L,
152
-10316L, -9840L, -9363L, -8883L, -8401L, -7917L, -7431L, -6943L,
153
-6454L, -5963L, -5471L, -4978L, -4483L, -3988L, -3491L, -2994L,
154
-2496L, -1998L, -1499L, -999L, -500L,
155
};
156
157
static byte capidtmf_leading_zeroes_table[0x100] =
158
{
159
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
160
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
161
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
162
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
163
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
164
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
165
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
166
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
167
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
168
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
169
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
170
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
171
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
172
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
173
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
174
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
175
};
176
177
#define capidtmf_byte_leading_zeroes(b) (capidtmf_leading_zeroes_table[(BYTE)(b)])
178
#define capidtmf_word_leading_zeroes(w) (((w) & 0xff00) ? capidtmf_leading_zeroes_table[(w) >> 8] : 8 + capidtmf_leading_zeroes_table[(w)])
179
#define capidtmf_dword_leading_zeroes(d) (((d) & 0xffff0000L) ? (((d) & 0xff000000L) ? capidtmf_leading_zeroes_table[(d) >> 24] : 8 + capidtmf_leading_zeroes_table[(d) >> 16]) : (((d) & 0xff00) ? 16 + capidtmf_leading_zeroes_table[(d) >> 8] : 24 + capidtmf_leading_zeroes_table[(d)]))
180
181
182
/*---------------------------------------------------------------------------*/
183
184
185
static void capidtmf_goertzel_loop (long *buffer, long *coeffs, short *sample, long count)
186
{
187
int i, j;
188
long c, d, q0, q1, q2;
189
190
for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT - 1; i++)
191
{
192
q1 = buffer[i];
193
q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
194
d = coeffs[i] >> 1;
195
c = d << 1;
196
if (c >= 0)
197
{
198
for (j = 0; j < count; j++)
199
{
200
q0 = sample[j] - q2 + (c * (q1 >> 16)) + (((dword)(((dword) d) * ((dword)(q1 & 0xffff)))) >> 15);
201
q2 = q1;
202
q1 = q0;
203
}
204
}
205
else
206
{
207
c = -c;
208
d = -d;
209
for (j = 0; j < count; j++)
210
{
211
q0 = sample[j] - q2 - ((c * (q1 >> 16)) + (((dword)(((dword) d) * ((dword)(q1 & 0xffff)))) >> 15));
212
q2 = q1;
213
q1 = q0;
214
}
215
}
216
buffer[i] = q1;
217
buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = q2;
218
}
219
q1 = buffer[i];
220
q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
221
c = (coeffs[i] >> 1) << 1;
222
if (c >= 0)
223
{
224
for (j = 0; j < count; j++)
225
{
226
q0 = sample[j] - q2 + (c * (q1 >> 16)) + (((dword)(((dword)(c >> 1)) * ((dword)(q1 & 0xffff)))) >> 15);
227
q2 = q1;
228
q1 = q0;
229
c -= CAPIDTMF_RECV_FUNDAMENTAL_DECREMENT;
230
}
231
}
232
else
233
{
234
c = -c;
235
for (j = 0; j < count; j++)
236
{
237
q0 = sample[j] - q2 - ((c * (q1 >> 16)) + (((dword)(((dword)(c >> 1)) * ((dword)(q1 & 0xffff)))) >> 15));
238
q2 = q1;
239
q1 = q0;
240
c += CAPIDTMF_RECV_FUNDAMENTAL_DECREMENT;
241
}
242
}
243
coeffs[i] = c;
244
buffer[i] = q1;
245
buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = q2;
246
}
247
248
249
static void capidtmf_goertzel_result (long *buffer, long *coeffs)
250
{
251
int i;
252
long d, e, q1, q2, lo, mid, hi;
253
dword k;
254
255
for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
256
{
257
q1 = buffer[i];
258
q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
259
d = coeffs[i] >> 1;
260
if (d >= 0)
261
d = ((d << 1) * (-q1 >> 16)) + (((dword)(((dword) d) * ((dword)(-q1 & 0xffff)))) >> 15);
262
else
263
d = ((-d << 1) * (-q1 >> 16)) + (((dword)(((dword) -d) * ((dword)(-q1 & 0xffff)))) >> 15);
264
e = (q2 >= 0) ? q2 : -q2;
265
if (d >= 0)
266
{
267
k = ((dword)(d & 0xffff)) * ((dword)(e & 0xffff));
268
lo = k & 0xffff;
269
mid = k >> 16;
270
k = ((dword)(d >> 16)) * ((dword)(e & 0xffff));
271
mid += k & 0xffff;
272
hi = k >> 16;
273
k = ((dword)(d & 0xffff)) * ((dword)(e >> 16));
274
mid += k & 0xffff;
275
hi += k >> 16;
276
hi += ((dword)(d >> 16)) * ((dword)(e >> 16));
277
}
278
else
279
{
280
d = -d;
281
k = ((dword)(d & 0xffff)) * ((dword)(e & 0xffff));
282
lo = -((long)(k & 0xffff));
283
mid = -((long)(k >> 16));
284
k = ((dword)(d >> 16)) * ((dword)(e & 0xffff));
285
mid -= k & 0xffff;
286
hi = -((long)(k >> 16));
287
k = ((dword)(d & 0xffff)) * ((dword)(e >> 16));
288
mid -= k & 0xffff;
289
hi -= k >> 16;
290
hi -= ((dword)(d >> 16)) * ((dword)(e >> 16));
291
}
292
if (q2 < 0)
293
{
294
lo = -lo;
295
mid = -mid;
296
hi = -hi;
297
}
298
d = (q1 >= 0) ? q1 : -q1;
299
k = ((dword)(d & 0xffff)) * ((dword)(d & 0xffff));
300
lo += k & 0xffff;
301
mid += k >> 16;
302
k = ((dword)(d >> 16)) * ((dword)(d & 0xffff));
303
mid += (k & 0xffff) << 1;
304
hi += (k >> 16) << 1;
305
hi += ((dword)(d >> 16)) * ((dword)(d >> 16));
306
d = (q2 >= 0) ? q2 : -q2;
307
k = ((dword)(d & 0xffff)) * ((dword)(d & 0xffff));
308
lo += k & 0xffff;
309
mid += k >> 16;
310
k = ((dword)(d >> 16)) * ((dword)(d & 0xffff));
311
mid += (k & 0xffff) << 1;
312
hi += (k >> 16) << 1;
313
hi += ((dword)(d >> 16)) * ((dword)(d >> 16));
314
mid += lo >> 16;
315
hi += mid >> 16;
316
buffer[i] = (lo & 0xffff) | (mid << 16);
317
buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = hi;
318
}
319
}
320
321
322
/*---------------------------------------------------------------------------*/
323
324
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_697 0
325
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_770 1
326
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_852 2
327
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_941 3
328
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1209 4
329
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1336 5
330
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1477 6
331
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1633 7
332
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_635 8
333
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1010 9
334
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1140 10
335
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1272 11
336
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1405 12
337
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1555 13
338
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1715 14
339
#define CAPIDTMF_RECV_GUARD_SNR_INDEX_1875 15
340
341
#define CAPIDTMF_RECV_GUARD_SNR_DONTCARE 0xc000
342
#define CAPIDTMF_RECV_NO_DIGIT 0xff
343
#define CAPIDTMF_RECV_TIME_GRANULARITY (CAPIDTMF_RECV_ACCUMULATE_CYCLES + 1)
344
345
#define CAPIDTMF_RECV_INDICATION_DIGIT 0x0001
346
347
static long capidtmf_recv_goertzel_coef_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
348
{
349
0xda97L * 2, /* 697 Hz (Low group 697 Hz) */
350
0xd299L * 2, /* 770 Hz (Low group 770 Hz) */
351
0xc8cbL * 2, /* 852 Hz (Low group 852 Hz) */
352
0xbd36L * 2, /* 941 Hz (Low group 941 Hz) */
353
0x9501L * 2, /* 1209 Hz (High group 1209 Hz) */
354
0x7f89L * 2, /* 1336 Hz (High group 1336 Hz) */
355
0x6639L * 2, /* 1477 Hz (High group 1477 Hz) */
356
0x48c6L * 2, /* 1633 Hz (High group 1633 Hz) */
357
0xe14cL * 2, /* 630 Hz (Lower guard of low group 631 Hz) */
358
0xb2e0L * 2, /* 1015 Hz (Upper guard of low group 1039 Hz) */
359
0xa1a0L * 2, /* 1130 Hz (Lower guard of high group 1140 Hz) */
360
0x8a87L * 2, /* 1272 Hz (Guard between 1209 Hz and 1336 Hz: 1271 Hz) */
361
0x7353L * 2, /* 1405 Hz (2nd harmonics of 697 Hz and guard between 1336 Hz and 1477 Hz: 1405 Hz) */
362
0x583bL * 2, /* 1552 Hz (2nd harmonics of 770 Hz and guard between 1477 Hz and 1633 Hz: 1553 Hz) */
363
0x37d8L * 2, /* 1720 Hz (2nd harmonics of 852 Hz and upper guard of high group: 1715 Hz) */
364
0x0000L * 2 /* 100-630 Hz (fundamentals) */
365
};
366
367
368
static word capidtmf_recv_guard_snr_low_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
369
{
370
14, /* Low group peak versus 697 Hz */
371
14, /* Low group peak versus 770 Hz */
372
16, /* Low group peak versus 852 Hz */
373
16, /* Low group peak versus 941 Hz */
374
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1209 Hz */
375
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1336 Hz */
376
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1477 Hz */
377
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1633 Hz */
378
14, /* Low group peak versus 635 Hz */
379
16, /* Low group peak versus 1010 Hz */
380
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1140 Hz */
381
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* Low group peak versus 1272 Hz */
382
DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 8, /* Low group peak versus 1405 Hz */
383
DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 4, /* Low group peak versus 1555 Hz */
384
DSPDTMF_RX_HARMONICS_SEL_DEFAULT - 4, /* Low group peak versus 1715 Hz */
385
12 /* Low group peak versus 100-630 Hz */
386
};
387
388
389
static word capidtmf_recv_guard_snr_high_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
390
{
391
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 697 Hz */
392
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 770 Hz */
393
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 852 Hz */
394
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 941 Hz */
395
20, /* High group peak versus 1209 Hz */
396
20, /* High group peak versus 1336 Hz */
397
20, /* High group peak versus 1477 Hz */
398
20, /* High group peak versus 1633 Hz */
399
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 635 Hz */
400
CAPIDTMF_RECV_GUARD_SNR_DONTCARE, /* High group peak versus 1010 Hz */
401
16, /* High group peak versus 1140 Hz */
402
4, /* High group peak versus 1272 Hz */
403
6, /* High group peak versus 1405 Hz */
404
8, /* High group peak versus 1555 Hz */
405
16, /* High group peak versus 1715 Hz */
406
12 /* High group peak versus 100-630 Hz */
407
};
408
409
410
/*---------------------------------------------------------------------------*/
411
412
static void capidtmf_recv_init (t_capidtmf_state *p_state)
413
{
414
p_state->recv.min_gap_duration = 1;
415
p_state->recv.min_digit_duration = 1;
416
417
p_state->recv.cycle_counter = 0;
418
p_state->recv.current_digit_on_time = 0;
419
p_state->recv.current_digit_off_time = 0;
420
p_state->recv.current_digit_value = CAPIDTMF_RECV_NO_DIGIT;
421
422
p_state->recv.digit_write_pos = 0;
423
p_state->recv.digit_read_pos = 0;
424
p_state->recv.indication_state = 0;
425
p_state->recv.indication_state_ack = 0;
426
p_state->recv.state = CAPIDTMF_RECV_STATE_IDLE;
427
}
428
429
430
void capidtmf_recv_enable (t_capidtmf_state *p_state, word min_digit_duration, word min_gap_duration)
431
{
432
p_state->recv.indication_state_ack &= CAPIDTMF_RECV_INDICATION_DIGIT;
433
p_state->recv.min_digit_duration = (word)(((((dword) min_digit_duration) * 8) +
434
((dword)(CAPIDTMF_RECV_TIME_GRANULARITY / 2))) / ((dword) CAPIDTMF_RECV_TIME_GRANULARITY));
435
if (p_state->recv.min_digit_duration <= 1)
436
p_state->recv.min_digit_duration = 1;
437
else
438
(p_state->recv.min_digit_duration)--;
439
p_state->recv.min_gap_duration =
440
(word)((((dword) min_gap_duration) * 8) / ((dword) CAPIDTMF_RECV_TIME_GRANULARITY));
441
if (p_state->recv.min_gap_duration <= 1)
442
p_state->recv.min_gap_duration = 1;
443
else
444
(p_state->recv.min_gap_duration)--;
445
p_state->recv.state |= CAPIDTMF_RECV_STATE_DTMF_ACTIVE;
446
}
447
448
449
void capidtmf_recv_disable (t_capidtmf_state *p_state)
450
{
451
p_state->recv.state &= ~CAPIDTMF_RECV_STATE_DTMF_ACTIVE;
452
if (p_state->recv.state == CAPIDTMF_RECV_STATE_IDLE)
453
capidtmf_recv_init (p_state);
454
else
455
{
456
p_state->recv.cycle_counter = 0;
457
p_state->recv.current_digit_on_time = 0;
458
p_state->recv.current_digit_off_time = 0;
459
p_state->recv.current_digit_value = CAPIDTMF_RECV_NO_DIGIT;
460
}
461
}
462
463
464
word capidtmf_recv_indication (t_capidtmf_state *p_state, byte *buffer)
465
{
466
word i, j, k, flags;
467
468
flags = p_state->recv.indication_state ^ p_state->recv.indication_state_ack;
469
p_state->recv.indication_state_ack ^= flags & CAPIDTMF_RECV_INDICATION_DIGIT;
470
if (p_state->recv.digit_write_pos != p_state->recv.digit_read_pos)
471
{
472
i = 0;
473
k = p_state->recv.digit_write_pos;
474
j = p_state->recv.digit_read_pos;
475
do
476
{
477
buffer[i++] = p_state->recv.digit_buffer[j];
478
j = (j == CAPIDTMF_RECV_DIGIT_BUFFER_SIZE - 1) ? 0 : j + 1;
479
} while (j != k);
480
p_state->recv.digit_read_pos = k;
481
return (i);
482
}
483
p_state->recv.indication_state_ack ^= flags;
484
return (0);
485
}
486
487
488
#define CAPIDTMF_RECV_WINDOWED_SAMPLES 32
489
490
void capidtmf_recv_block (t_capidtmf_state *p_state, byte *buffer, word length)
491
{
492
byte result_digit;
493
word sample_number, cycle_counter, n, i;
494
word low_peak, high_peak;
495
dword lo, hi;
496
byte *p;
497
short *q;
498
byte goertzel_result_buffer[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
499
short windowed_sample_buffer[CAPIDTMF_RECV_WINDOWED_SAMPLES];
500
501
502
if (p_state->recv.state & CAPIDTMF_RECV_STATE_DTMF_ACTIVE)
503
{
504
cycle_counter = p_state->recv.cycle_counter;
505
sample_number = 0;
506
while (sample_number < length)
507
{
508
if (cycle_counter < CAPIDTMF_RECV_ACCUMULATE_CYCLES)
509
{
510
if (cycle_counter == 0)
511
{
512
for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
513
{
514
p_state->recv.goertzel_buffer[0][i] = 0;
515
p_state->recv.goertzel_buffer[1][i] = 0;
516
}
517
}
518
n = CAPIDTMF_RECV_ACCUMULATE_CYCLES - cycle_counter;
519
if (n > length - sample_number)
520
n = length - sample_number;
521
if (n > CAPIDTMF_RECV_WINDOWED_SAMPLES)
522
n = CAPIDTMF_RECV_WINDOWED_SAMPLES;
523
p = buffer + sample_number;
524
q = capidtmf_recv_window_function + cycle_counter;
525
if (p_state->ulaw)
526
{
527
for (i = 0; i < n; i++)
528
{
529
windowed_sample_buffer[i] =
530
(short)((capidtmf_expand_table_ulaw[p[i]] * ((long)(q[i]))) >> 15);
531
}
532
}
533
else
534
{
535
for (i = 0; i < n; i++)
536
{
537
windowed_sample_buffer[i] =
538
(short)((capidtmf_expand_table_alaw[p[i]] * ((long)(q[i]))) >> 15);
539
}
540
}
541
capidtmf_recv_goertzel_coef_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT - 1] = CAPIDTMF_RECV_FUNDAMENTAL_OFFSET;
542
capidtmf_goertzel_loop (p_state->recv.goertzel_buffer[0],
543
capidtmf_recv_goertzel_coef_table, windowed_sample_buffer, n);
544
cycle_counter += n;
545
sample_number += n;
546
}
547
else
548
{
549
capidtmf_goertzel_result (p_state->recv.goertzel_buffer[0],
550
capidtmf_recv_goertzel_coef_table);
551
for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
552
{
553
lo = (dword)(p_state->recv.goertzel_buffer[0][i]);
554
hi = (dword)(p_state->recv.goertzel_buffer[1][i]);
555
if (hi != 0)
556
{
557
n = capidtmf_dword_leading_zeroes (hi);
558
hi = (hi << n) | (lo >> (32 - n));
559
}
560
else
561
{
562
n = capidtmf_dword_leading_zeroes (lo);
563
hi = lo << n;
564
n += 32;
565
}
566
n = 195 - 3 * n;
567
if (hi >= 0xcb300000L)
568
n += 2;
569
else if (hi >= 0xa1450000L)
570
n++;
571
goertzel_result_buffer[i] = (byte) n;
572
}
573
low_peak = DSPDTMF_RX_SENSITIVITY_LOW_DEFAULT;
574
result_digit = CAPIDTMF_RECV_NO_DIGIT;
575
for (i = 0; i < CAPIDTMF_LOW_GROUP_FREQUENCIES; i++)
576
{
577
if (goertzel_result_buffer[i] > low_peak)
578
{
579
low_peak = goertzel_result_buffer[i];
580
result_digit = (byte) i;
581
}
582
}
583
high_peak = DSPDTMF_RX_SENSITIVITY_HIGH_DEFAULT;
584
n = CAPIDTMF_RECV_NO_DIGIT;
585
for (i = CAPIDTMF_LOW_GROUP_FREQUENCIES; i < CAPIDTMF_RECV_BASE_FREQUENCY_COUNT; i++)
586
{
587
if (goertzel_result_buffer[i] > high_peak)
588
{
589
high_peak = goertzel_result_buffer[i];
590
n = (i - CAPIDTMF_LOW_GROUP_FREQUENCIES) << 2;
591
}
592
}
593
result_digit |= (byte) n;
594
if (low_peak + DSPDTMF_RX_HIGH_EXCEEDING_LOW_DEFAULT < high_peak)
595
result_digit = CAPIDTMF_RECV_NO_DIGIT;
596
if (high_peak + DSPDTMF_RX_LOW_EXCEEDING_HIGH_DEFAULT < low_peak)
597
result_digit = CAPIDTMF_RECV_NO_DIGIT;
598
n = 0;
599
for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
600
{
601
if ((((short)(low_peak - goertzel_result_buffer[i] - capidtmf_recv_guard_snr_low_table[i])) < 0)
602
|| (((short)(high_peak - goertzel_result_buffer[i] - capidtmf_recv_guard_snr_high_table[i])) < 0))
603
{
604
n++;
605
}
606
}
607
if (n != 2)
608
result_digit = CAPIDTMF_RECV_NO_DIGIT;
609
610
if (result_digit == CAPIDTMF_RECV_NO_DIGIT)
611
{
612
if (p_state->recv.current_digit_on_time != 0)
613
{
614
if (++(p_state->recv.current_digit_off_time) >= p_state->recv.min_gap_duration)
615
{
616
p_state->recv.current_digit_on_time = 0;
617
p_state->recv.current_digit_off_time = 0;
618
}
619
}
620
else
621
{
622
if (p_state->recv.current_digit_off_time != 0)
623
(p_state->recv.current_digit_off_time)--;
624
}
625
}
626
else
627
{
628
if ((p_state->recv.current_digit_on_time == 0)
629
&& (p_state->recv.current_digit_off_time != 0))
630
{
631
(p_state->recv.current_digit_off_time)--;
632
}
633
else
634
{
635
n = p_state->recv.current_digit_off_time;
636
if ((p_state->recv.current_digit_on_time != 0)
637
&& (result_digit != p_state->recv.current_digit_value))
638
{
639
p_state->recv.current_digit_on_time = 0;
640
n = 0;
641
}
642
p_state->recv.current_digit_value = result_digit;
643
p_state->recv.current_digit_off_time = 0;
644
if (p_state->recv.current_digit_on_time != 0xffff)
645
{
646
p_state->recv.current_digit_on_time += n + 1;
647
if (p_state->recv.current_digit_on_time >= p_state->recv.min_digit_duration)
648
{
649
p_state->recv.current_digit_on_time = 0xffff;
650
i = (p_state->recv.digit_write_pos == CAPIDTMF_RECV_DIGIT_BUFFER_SIZE - 1) ?
651
0 : p_state->recv.digit_write_pos + 1;
652
if (i == p_state->recv.digit_read_pos)
653
{
654
trace (dprintf ("%s,%d: Receive digit overrun",
655
(char *)(FILE_), __LINE__));
656
}
657
else
658
{
659
p_state->recv.digit_buffer[p_state->recv.digit_write_pos] = result_digit;
660
p_state->recv.digit_write_pos = i;
661
p_state->recv.indication_state =
662
(p_state->recv.indication_state & ~CAPIDTMF_RECV_INDICATION_DIGIT) |
663
(~p_state->recv.indication_state_ack & CAPIDTMF_RECV_INDICATION_DIGIT);
664
}
665
}
666
}
667
}
668
}
669
cycle_counter = 0;
670
sample_number++;
671
}
672
}
673
p_state->recv.cycle_counter = cycle_counter;
674
}
675
}
676
677
678
void capidtmf_init (t_capidtmf_state *p_state, byte ulaw)
679
{
680
p_state->ulaw = ulaw;
681
capidtmf_recv_init (p_state);
682
}
683
684
685
/*---------------------------------------------------------------------------*/
686
687