1*960366cfSKarsten Keil /* 2*960366cfSKarsten Keil * DTMF decoder. 3*960366cfSKarsten Keil * 4*960366cfSKarsten Keil * Copyright by Andreas Eversberg (jolly@eversberg.eu) 5*960366cfSKarsten Keil * based on different decoders such as ISDN4Linux 6*960366cfSKarsten Keil * 7*960366cfSKarsten Keil * This software may be used and distributed according to the terms 8*960366cfSKarsten Keil * of the GNU General Public License, incorporated herein by reference. 9*960366cfSKarsten Keil * 10*960366cfSKarsten Keil */ 11*960366cfSKarsten Keil 12*960366cfSKarsten Keil #include <linux/mISDNif.h> 13*960366cfSKarsten Keil #include <linux/mISDNdsp.h> 14*960366cfSKarsten Keil #include "core.h" 15*960366cfSKarsten Keil #include "dsp.h" 16*960366cfSKarsten Keil 17*960366cfSKarsten Keil #define NCOEFF 8 /* number of frequencies to be analyzed */ 18*960366cfSKarsten Keil 19*960366cfSKarsten Keil /* For DTMF recognition: 20*960366cfSKarsten Keil * 2 * cos(2 * PI * k / N) precalculated for all k 21*960366cfSKarsten Keil */ 22*960366cfSKarsten Keil static u64 cos2pik[NCOEFF] = 23*960366cfSKarsten Keil { 24*960366cfSKarsten Keil /* k << 15 (source: hfc-4s/8s documentation (www.colognechip.de)) */ 25*960366cfSKarsten Keil 55960, 53912, 51402, 48438, 38146, 32650, 26170, 18630 26*960366cfSKarsten Keil }; 27*960366cfSKarsten Keil 28*960366cfSKarsten Keil /* digit matrix */ 29*960366cfSKarsten Keil static char dtmf_matrix[4][4] = 30*960366cfSKarsten Keil { 31*960366cfSKarsten Keil {'1', '2', '3', 'A'}, 32*960366cfSKarsten Keil {'4', '5', '6', 'B'}, 33*960366cfSKarsten Keil {'7', '8', '9', 'C'}, 34*960366cfSKarsten Keil {'*', '0', '#', 'D'} 35*960366cfSKarsten Keil }; 36*960366cfSKarsten Keil 37*960366cfSKarsten Keil /* dtmf detection using goertzel algorithm 38*960366cfSKarsten Keil * init function 39*960366cfSKarsten Keil */ 40*960366cfSKarsten Keil void dsp_dtmf_goertzel_init(struct dsp *dsp) 41*960366cfSKarsten Keil { 42*960366cfSKarsten Keil dsp->dtmf.size = 0; 43*960366cfSKarsten Keil dsp->dtmf.lastwhat = '\0'; 44*960366cfSKarsten Keil dsp->dtmf.lastdigit = '\0'; 45*960366cfSKarsten Keil dsp->dtmf.count = 0; 46*960366cfSKarsten Keil } 47*960366cfSKarsten Keil 48*960366cfSKarsten Keil /* check for hardware or software features 49*960366cfSKarsten Keil */ 50*960366cfSKarsten Keil void dsp_dtmf_hardware(struct dsp *dsp) 51*960366cfSKarsten Keil { 52*960366cfSKarsten Keil int hardware = 1; 53*960366cfSKarsten Keil 54*960366cfSKarsten Keil if (!dsp->features.hfc_dtmf) 55*960366cfSKarsten Keil hardware = 0; 56*960366cfSKarsten Keil 57*960366cfSKarsten Keil /* check for volume change */ 58*960366cfSKarsten Keil if (dsp->tx_volume) { 59*960366cfSKarsten Keil if (dsp_debug & DEBUG_DSP_DTMF) 60*960366cfSKarsten Keil printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, " 61*960366cfSKarsten Keil "because tx_volume is changed\n", 62*960366cfSKarsten Keil __func__, dsp->name); 63*960366cfSKarsten Keil hardware = 0; 64*960366cfSKarsten Keil } 65*960366cfSKarsten Keil if (dsp->rx_volume) { 66*960366cfSKarsten Keil if (dsp_debug & DEBUG_DSP_DTMF) 67*960366cfSKarsten Keil printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, " 68*960366cfSKarsten Keil "because rx_volume is changed\n", 69*960366cfSKarsten Keil __func__, dsp->name); 70*960366cfSKarsten Keil hardware = 0; 71*960366cfSKarsten Keil } 72*960366cfSKarsten Keil /* check if encryption is enabled */ 73*960366cfSKarsten Keil if (dsp->bf_enable) { 74*960366cfSKarsten Keil if (dsp_debug & DEBUG_DSP_DTMF) 75*960366cfSKarsten Keil printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, " 76*960366cfSKarsten Keil "because encryption is enabled\n", 77*960366cfSKarsten Keil __func__, dsp->name); 78*960366cfSKarsten Keil hardware = 0; 79*960366cfSKarsten Keil } 80*960366cfSKarsten Keil /* check if pipeline exists */ 81*960366cfSKarsten Keil if (dsp->pipeline.inuse) { 82*960366cfSKarsten Keil if (dsp_debug & DEBUG_DSP_DTMF) 83*960366cfSKarsten Keil printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, " 84*960366cfSKarsten Keil "because pipeline exists.\n", 85*960366cfSKarsten Keil __func__, dsp->name); 86*960366cfSKarsten Keil hardware = 0; 87*960366cfSKarsten Keil } 88*960366cfSKarsten Keil 89*960366cfSKarsten Keil dsp->dtmf.hardware = hardware; 90*960366cfSKarsten Keil dsp->dtmf.software = !hardware; 91*960366cfSKarsten Keil } 92*960366cfSKarsten Keil 93*960366cfSKarsten Keil 94*960366cfSKarsten Keil /************************************************************* 95*960366cfSKarsten Keil * calculate the coefficients of the given sample and decode * 96*960366cfSKarsten Keil *************************************************************/ 97*960366cfSKarsten Keil 98*960366cfSKarsten Keil /* the given sample is decoded. if the sample is not long enough for a 99*960366cfSKarsten Keil * complete frame, the decoding is finished and continued with the next 100*960366cfSKarsten Keil * call of this function. 101*960366cfSKarsten Keil * 102*960366cfSKarsten Keil * the algorithm is very good for detection with a minimum of errors. i 103*960366cfSKarsten Keil * tested it allot. it even works with very short tones (40ms). the only 104*960366cfSKarsten Keil * disadvantage is, that it doesn't work good with different volumes of both 105*960366cfSKarsten Keil * tones. this will happen, if accoustically coupled dialers are used. 106*960366cfSKarsten Keil * it sometimes detects tones during speach, which is normal for decoders. 107*960366cfSKarsten Keil * use sequences to given commands during calls. 108*960366cfSKarsten Keil * 109*960366cfSKarsten Keil * dtmf - points to a structure of the current dtmf state 110*960366cfSKarsten Keil * spl and len - the sample 111*960366cfSKarsten Keil * fmt - 0 = alaw, 1 = ulaw, 2 = coefficients from HFC DTMF hw-decoder 112*960366cfSKarsten Keil */ 113*960366cfSKarsten Keil 114*960366cfSKarsten Keil u8 115*960366cfSKarsten Keil *dsp_dtmf_goertzel_decode(struct dsp *dsp, u8 *data, int len, int fmt) 116*960366cfSKarsten Keil { 117*960366cfSKarsten Keil u8 what; 118*960366cfSKarsten Keil int size; 119*960366cfSKarsten Keil signed short *buf; 120*960366cfSKarsten Keil s32 sk, sk1, sk2; 121*960366cfSKarsten Keil int k, n, i; 122*960366cfSKarsten Keil s32 *hfccoeff; 123*960366cfSKarsten Keil s32 result[NCOEFF], tresh, treshl; 124*960366cfSKarsten Keil int lowgroup, highgroup; 125*960366cfSKarsten Keil s64 cos2pik_; 126*960366cfSKarsten Keil 127*960366cfSKarsten Keil dsp->dtmf.digits[0] = '\0'; 128*960366cfSKarsten Keil 129*960366cfSKarsten Keil /* Note: The function will loop until the buffer has not enough samples 130*960366cfSKarsten Keil * left to decode a full frame. 131*960366cfSKarsten Keil */ 132*960366cfSKarsten Keil again: 133*960366cfSKarsten Keil /* convert samples */ 134*960366cfSKarsten Keil size = dsp->dtmf.size; 135*960366cfSKarsten Keil buf = dsp->dtmf.buffer; 136*960366cfSKarsten Keil switch (fmt) { 137*960366cfSKarsten Keil case 0: /* alaw */ 138*960366cfSKarsten Keil case 1: /* ulaw */ 139*960366cfSKarsten Keil while (size < DSP_DTMF_NPOINTS && len) { 140*960366cfSKarsten Keil buf[size++] = dsp_audio_law_to_s32[*data++]; 141*960366cfSKarsten Keil len--; 142*960366cfSKarsten Keil } 143*960366cfSKarsten Keil break; 144*960366cfSKarsten Keil 145*960366cfSKarsten Keil case 2: /* HFC coefficients */ 146*960366cfSKarsten Keil default: 147*960366cfSKarsten Keil if (len < 64) { 148*960366cfSKarsten Keil if (len > 0) 149*960366cfSKarsten Keil printk(KERN_ERR "%s: coefficients have invalid " 150*960366cfSKarsten Keil "size. (is=%d < must=%d)\n", 151*960366cfSKarsten Keil __func__, len, 64); 152*960366cfSKarsten Keil return dsp->dtmf.digits; 153*960366cfSKarsten Keil } 154*960366cfSKarsten Keil hfccoeff = (s32 *)data; 155*960366cfSKarsten Keil for (k = 0; k < NCOEFF; k++) { 156*960366cfSKarsten Keil sk2 = (*hfccoeff++)>>4; 157*960366cfSKarsten Keil sk = (*hfccoeff++)>>4; 158*960366cfSKarsten Keil if (sk > 32767 || sk < -32767 || sk2 > 32767 159*960366cfSKarsten Keil || sk2 < -32767) 160*960366cfSKarsten Keil printk(KERN_WARNING 161*960366cfSKarsten Keil "DTMF-Detection overflow\n"); 162*960366cfSKarsten Keil /* compute |X(k)|**2 */ 163*960366cfSKarsten Keil result[k] = 164*960366cfSKarsten Keil (sk * sk) - 165*960366cfSKarsten Keil (((cos2pik[k] * sk) >> 15) * sk2) + 166*960366cfSKarsten Keil (sk2 * sk2); 167*960366cfSKarsten Keil } 168*960366cfSKarsten Keil data += 64; 169*960366cfSKarsten Keil len -= 64; 170*960366cfSKarsten Keil goto coefficients; 171*960366cfSKarsten Keil break; 172*960366cfSKarsten Keil } 173*960366cfSKarsten Keil dsp->dtmf.size = size; 174*960366cfSKarsten Keil 175*960366cfSKarsten Keil if (size < DSP_DTMF_NPOINTS) 176*960366cfSKarsten Keil return dsp->dtmf.digits; 177*960366cfSKarsten Keil 178*960366cfSKarsten Keil dsp->dtmf.size = 0; 179*960366cfSKarsten Keil 180*960366cfSKarsten Keil /* now we have a full buffer of signed long samples - we do goertzel */ 181*960366cfSKarsten Keil for (k = 0; k < NCOEFF; k++) { 182*960366cfSKarsten Keil sk = 0; 183*960366cfSKarsten Keil sk1 = 0; 184*960366cfSKarsten Keil sk2 = 0; 185*960366cfSKarsten Keil buf = dsp->dtmf.buffer; 186*960366cfSKarsten Keil cos2pik_ = cos2pik[k]; 187*960366cfSKarsten Keil for (n = 0; n < DSP_DTMF_NPOINTS; n++) { 188*960366cfSKarsten Keil sk = ((cos2pik_*sk1)>>15) - sk2 + (*buf++); 189*960366cfSKarsten Keil sk2 = sk1; 190*960366cfSKarsten Keil sk1 = sk; 191*960366cfSKarsten Keil } 192*960366cfSKarsten Keil sk >>= 8; 193*960366cfSKarsten Keil sk2 >>= 8; 194*960366cfSKarsten Keil if (sk > 32767 || sk < -32767 || sk2 > 32767 || sk2 < -32767) 195*960366cfSKarsten Keil printk(KERN_WARNING "DTMF-Detection overflow\n"); 196*960366cfSKarsten Keil /* compute |X(k)|**2 */ 197*960366cfSKarsten Keil result[k] = 198*960366cfSKarsten Keil (sk * sk) - 199*960366cfSKarsten Keil (((cos2pik[k] * sk) >> 15) * sk2) + 200*960366cfSKarsten Keil (sk2 * sk2); 201*960366cfSKarsten Keil } 202*960366cfSKarsten Keil 203*960366cfSKarsten Keil /* our (squared) coefficients have been calculated, we need to process 204*960366cfSKarsten Keil * them. 205*960366cfSKarsten Keil */ 206*960366cfSKarsten Keil coefficients: 207*960366cfSKarsten Keil tresh = 0; 208*960366cfSKarsten Keil for (i = 0; i < NCOEFF; i++) { 209*960366cfSKarsten Keil if (result[i] < 0) 210*960366cfSKarsten Keil result[i] = 0; 211*960366cfSKarsten Keil if (result[i] > dsp->dtmf.treshold) { 212*960366cfSKarsten Keil if (result[i] > tresh) 213*960366cfSKarsten Keil tresh = result[i]; 214*960366cfSKarsten Keil } 215*960366cfSKarsten Keil } 216*960366cfSKarsten Keil 217*960366cfSKarsten Keil if (tresh == 0) { 218*960366cfSKarsten Keil what = 0; 219*960366cfSKarsten Keil goto storedigit; 220*960366cfSKarsten Keil } 221*960366cfSKarsten Keil 222*960366cfSKarsten Keil if (dsp_debug & DEBUG_DSP_DTMFCOEFF) 223*960366cfSKarsten Keil printk(KERN_DEBUG "a %3d %3d %3d %3d %3d %3d %3d %3d" 224*960366cfSKarsten Keil " tr:%3d r %3d %3d %3d %3d %3d %3d %3d %3d\n", 225*960366cfSKarsten Keil result[0]/10000, result[1]/10000, result[2]/10000, 226*960366cfSKarsten Keil result[3]/10000, result[4]/10000, result[5]/10000, 227*960366cfSKarsten Keil result[6]/10000, result[7]/10000, tresh/10000, 228*960366cfSKarsten Keil result[0]/(tresh/100), result[1]/(tresh/100), 229*960366cfSKarsten Keil result[2]/(tresh/100), result[3]/(tresh/100), 230*960366cfSKarsten Keil result[4]/(tresh/100), result[5]/(tresh/100), 231*960366cfSKarsten Keil result[6]/(tresh/100), result[7]/(tresh/100)); 232*960366cfSKarsten Keil 233*960366cfSKarsten Keil /* calc digit (lowgroup/highgroup) */ 234*960366cfSKarsten Keil lowgroup = -1; 235*960366cfSKarsten Keil highgroup = -1; 236*960366cfSKarsten Keil treshl = tresh >> 3; /* tones which are not on, must be below 9 dB */ 237*960366cfSKarsten Keil tresh = tresh >> 2; /* touchtones must match within 6 dB */ 238*960366cfSKarsten Keil for (i = 0; i < NCOEFF; i++) { 239*960366cfSKarsten Keil if (result[i] < treshl) 240*960366cfSKarsten Keil continue; /* ignore */ 241*960366cfSKarsten Keil if (result[i] < tresh) { 242*960366cfSKarsten Keil lowgroup = -1; 243*960366cfSKarsten Keil highgroup = -1; 244*960366cfSKarsten Keil break; /* noise inbetween */ 245*960366cfSKarsten Keil } 246*960366cfSKarsten Keil /* good level found. This is allowed only one time per group */ 247*960366cfSKarsten Keil if (i < NCOEFF/2) { 248*960366cfSKarsten Keil /* lowgroup */ 249*960366cfSKarsten Keil if (lowgroup >= 0) { 250*960366cfSKarsten Keil /* Bad. Another tone found. */ 251*960366cfSKarsten Keil lowgroup = -1; 252*960366cfSKarsten Keil break; 253*960366cfSKarsten Keil } else 254*960366cfSKarsten Keil lowgroup = i; 255*960366cfSKarsten Keil } else { 256*960366cfSKarsten Keil /* higroup */ 257*960366cfSKarsten Keil if (highgroup >= 0) { 258*960366cfSKarsten Keil /* Bad. Another tone found. */ 259*960366cfSKarsten Keil highgroup = -1; 260*960366cfSKarsten Keil break; 261*960366cfSKarsten Keil } else 262*960366cfSKarsten Keil highgroup = i-(NCOEFF/2); 263*960366cfSKarsten Keil } 264*960366cfSKarsten Keil } 265*960366cfSKarsten Keil 266*960366cfSKarsten Keil /* get digit or null */ 267*960366cfSKarsten Keil what = 0; 268*960366cfSKarsten Keil if (lowgroup >= 0 && highgroup >= 0) 269*960366cfSKarsten Keil what = dtmf_matrix[lowgroup][highgroup]; 270*960366cfSKarsten Keil 271*960366cfSKarsten Keil storedigit: 272*960366cfSKarsten Keil if (what && (dsp_debug & DEBUG_DSP_DTMF)) 273*960366cfSKarsten Keil printk(KERN_DEBUG "DTMF what: %c\n", what); 274*960366cfSKarsten Keil 275*960366cfSKarsten Keil if (dsp->dtmf.lastwhat != what) 276*960366cfSKarsten Keil dsp->dtmf.count = 0; 277*960366cfSKarsten Keil 278*960366cfSKarsten Keil /* the tone (or no tone) must remain 3 times without change */ 279*960366cfSKarsten Keil if (dsp->dtmf.count == 2) { 280*960366cfSKarsten Keil if (dsp->dtmf.lastdigit != what) { 281*960366cfSKarsten Keil dsp->dtmf.lastdigit = what; 282*960366cfSKarsten Keil if (what) { 283*960366cfSKarsten Keil if (dsp_debug & DEBUG_DSP_DTMF) 284*960366cfSKarsten Keil printk(KERN_DEBUG "DTMF digit: %c\n", 285*960366cfSKarsten Keil what); 286*960366cfSKarsten Keil if ((strlen(dsp->dtmf.digits)+1) 287*960366cfSKarsten Keil < sizeof(dsp->dtmf.digits)) { 288*960366cfSKarsten Keil dsp->dtmf.digits[strlen( 289*960366cfSKarsten Keil dsp->dtmf.digits)+1] = '\0'; 290*960366cfSKarsten Keil dsp->dtmf.digits[strlen( 291*960366cfSKarsten Keil dsp->dtmf.digits)] = what; 292*960366cfSKarsten Keil } 293*960366cfSKarsten Keil } 294*960366cfSKarsten Keil } 295*960366cfSKarsten Keil } else 296*960366cfSKarsten Keil dsp->dtmf.count++; 297*960366cfSKarsten Keil 298*960366cfSKarsten Keil dsp->dtmf.lastwhat = what; 299*960366cfSKarsten Keil 300*960366cfSKarsten Keil goto again; 301*960366cfSKarsten Keil } 302*960366cfSKarsten Keil 303*960366cfSKarsten Keil 304