Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
capidtmf.c
Go to the documentation of this file.
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;
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;
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;
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;
427 }
428 
429 
430 void capidtmf_recv_enable(t_capidtmf_state *p_state, word min_digit_duration, word min_gap_duration)
431 {
433  p_state->recv.min_digit_duration = (word)(((((dword) min_digit_duration) * 8) +
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)--;
446 }
447 
448 
450 {
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;
460  }
461 }
462 
463 
465 {
466  word i, j, k, flags;
467 
468  flags = p_state->recv.indication_state ^ p_state->recv.indication_state_ack;
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 
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 
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;
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  {
558  hi = (hi << n) | (lo >> (32 - n));
559  }
560  else
561  {
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  }
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  }
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;
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 =
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 
679 {
680  p_state->ulaw = ulaw;
681  capidtmf_recv_init(p_state);
682 }
683 
684 
685 /*---------------------------------------------------------------------------*/