Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / drivers / isdn / hardware / eicon / capidtmf.c
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 /*---------------------------------------------------------------------------*/