Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / drivers / isdn / hardware / eicon / capidtmf.c
blobf130724144f3e7bf7027734923e0c30c08bfeec7
2 /*
4 Copyright (c) Eicon Networks, 2002.
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
9 Eicon File Revision : 2.1
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.
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.
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.
27 #include "platform.h"
37 #include "capidtmf.h"
39 /* #define TRACE_ */
41 #define FILE_ "CAPIDTMF.C"
43 /*---------------------------------------------------------------------------*/
46 #define trace(a)
50 /*---------------------------------------------------------------------------*/
52 static short capidtmf_expand_table_alaw[0x0100] =
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
88 static short capidtmf_expand_table_ulaw[0x0100] =
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
125 /*---------------------------------------------------------------------------*/
127 static short capidtmf_recv_window_function[CAPIDTMF_RECV_ACCUMULATE_CYCLES] =
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,
157 static byte capidtmf_leading_zeroes_table[0x100] =
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
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)]))
182 /*---------------------------------------------------------------------------*/
185 static void capidtmf_goertzel_loop (long *buffer, long *coeffs, short *sample, long count)
187 int i, j;
188 long c, d, q0, q1, q2;
190 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT - 1; i++)
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)
198 for (j = 0; j < count; j++)
200 q0 = sample[j] - q2 + (c * (q1 >> 16)) + (((dword)(((dword) d) * ((dword)(q1 & 0xffff)))) >> 15);
201 q2 = q1;
202 q1 = q0;
205 else
207 c = -c;
208 d = -d;
209 for (j = 0; j < count; j++)
211 q0 = sample[j] - q2 - ((c * (q1 >> 16)) + (((dword)(((dword) d) * ((dword)(q1 & 0xffff)))) >> 15));
212 q2 = q1;
213 q1 = q0;
216 buffer[i] = q1;
217 buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = q2;
219 q1 = buffer[i];
220 q2 = buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT];
221 c = (coeffs[i] >> 1) << 1;
222 if (c >= 0)
224 for (j = 0; j < count; j++)
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;
232 else
234 c = -c;
235 for (j = 0; j < count; j++)
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;
243 coeffs[i] = c;
244 buffer[i] = q1;
245 buffer[i + CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] = q2;
249 static void capidtmf_goertzel_result (long *buffer, long *coeffs)
251 int i;
252 long d, e, q1, q2, lo, mid, hi;
253 dword k;
255 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
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)
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));
278 else
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));
292 if (q2 < 0)
294 lo = -lo;
295 mid = -mid;
296 hi = -hi;
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;
322 /*---------------------------------------------------------------------------*/
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
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)
345 #define CAPIDTMF_RECV_INDICATION_DIGIT 0x0001
347 static long capidtmf_recv_goertzel_coef_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
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) */
368 static word capidtmf_recv_guard_snr_low_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
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 */
389 static word capidtmf_recv_guard_snr_high_table[CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT] =
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 */
410 /*---------------------------------------------------------------------------*/
412 static void capidtmf_recv_init (t_capidtmf_state *p_state)
414 p_state->recv.min_gap_duration = 1;
415 p_state->recv.min_digit_duration = 1;
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;
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;
430 void capidtmf_recv_enable (t_capidtmf_state *p_state, word min_digit_duration, word min_gap_duration)
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;
449 void capidtmf_recv_disable (t_capidtmf_state *p_state)
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
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;
464 word capidtmf_recv_indication (t_capidtmf_state *p_state, byte *buffer)
466 word i, j, k, flags;
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)
472 i = 0;
473 k = p_state->recv.digit_write_pos;
474 j = p_state->recv.digit_read_pos;
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);
483 p_state->recv.indication_state_ack ^= flags;
484 return (0);
488 #define CAPIDTMF_RECV_WINDOWED_SAMPLES 32
490 void capidtmf_recv_block (t_capidtmf_state *p_state, byte *buffer, word length)
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];
502 if (p_state->recv.state & CAPIDTMF_RECV_STATE_DTMF_ACTIVE)
504 cycle_counter = p_state->recv.cycle_counter;
505 sample_number = 0;
506 while (sample_number < length)
508 if (cycle_counter < CAPIDTMF_RECV_ACCUMULATE_CYCLES)
510 if (cycle_counter == 0)
512 for (i = 0; i < CAPIDTMF_RECV_TOTAL_FREQUENCY_COUNT; i++)
514 p_state->recv.goertzel_buffer[0][i] = 0;
515 p_state->recv.goertzel_buffer[1][i] = 0;
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)
527 for (i = 0; i < n; i++)
529 windowed_sample_buffer[i] =
530 (short)((capidtmf_expand_table_ulaw[p[i]] * ((long)(q[i]))) >> 15);
533 else
535 for (i = 0; i < n; i++)
537 windowed_sample_buffer[i] =
538 (short)((capidtmf_expand_table_alaw[p[i]] * ((long)(q[i]))) >> 15);
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;
547 else
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++)
553 lo = (dword)(p_state->recv.goertzel_buffer[0][i]);
554 hi = (dword)(p_state->recv.goertzel_buffer[1][i]);
555 if (hi != 0)
557 n = capidtmf_dword_leading_zeroes (hi);
558 hi = (hi << n) | (lo >> (32 - n));
560 else
562 n = capidtmf_dword_leading_zeroes (lo);
563 hi = lo << n;
564 n += 32;
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;
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++)
577 if (goertzel_result_buffer[i] > low_peak)
579 low_peak = goertzel_result_buffer[i];
580 result_digit = (byte) i;
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++)
587 if (goertzel_result_buffer[i] > high_peak)
589 high_peak = goertzel_result_buffer[i];
590 n = (i - CAPIDTMF_LOW_GROUP_FREQUENCIES) << 2;
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++)
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))
604 n++;
607 if (n != 2)
608 result_digit = CAPIDTMF_RECV_NO_DIGIT;
610 if (result_digit == CAPIDTMF_RECV_NO_DIGIT)
612 if (p_state->recv.current_digit_on_time != 0)
614 if (++(p_state->recv.current_digit_off_time) >= p_state->recv.min_gap_duration)
616 p_state->recv.current_digit_on_time = 0;
617 p_state->recv.current_digit_off_time = 0;
620 else
622 if (p_state->recv.current_digit_off_time != 0)
623 (p_state->recv.current_digit_off_time)--;
626 else
628 if ((p_state->recv.current_digit_on_time == 0)
629 && (p_state->recv.current_digit_off_time != 0))
631 (p_state->recv.current_digit_off_time)--;
633 else
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))
639 p_state->recv.current_digit_on_time = 0;
640 n = 0;
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)
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)
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)
654 trace (dprintf ("%s,%d: Receive digit overrun",
655 (char *)(FILE_), __LINE__));
657 else
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);
669 cycle_counter = 0;
670 sample_number++;
673 p_state->recv.cycle_counter = cycle_counter;
678 void capidtmf_init (t_capidtmf_state *p_state, byte ulaw)
680 p_state->ulaw = ulaw;
681 capidtmf_recv_init (p_state);
685 /*---------------------------------------------------------------------------*/