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
52static 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
88static 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
127static 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
157static 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
185static 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
249static 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
347static 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
368static 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
389static 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
412static 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
430void 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
449void 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
464word 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
490void 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
678void 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