/*
 * DTMF decoder.
 *
 * Copyright            by Andreas Eversberg (jolly@eversberg.eu)
 *			based on different decoders such as ISDN4Linux
 *
 * This software may be used and distributed according to the terms
 * of the GNU General Public License, incorporated herein by reference.
 *
 */

#include <linux/mISDNif.h>
#include <linux/mISDNdsp.h>
#include "core.h"
#include "dsp.h"

#define NCOEFF            8     /* number of frequencies to be analyzed */

/* For DTMF recognition:
 * 2 * cos(2 * PI * k / N) precalculated for all k
 */
static u64 cos2pik[NCOEFF] =
{
	/* k << 15 (source: hfc-4s/8s documentation (www.colognechip.de)) */
	55960, 53912, 51402, 48438, 38146, 32650, 26170, 18630
};

/* digit matrix */
static char dtmf_matrix[4][4] =
{
	{'1', '2', '3', 'A'},
	{'4', '5', '6', 'B'},
	{'7', '8', '9', 'C'},
	{'*', '0', '#', 'D'}
};

/* dtmf detection using goertzel algorithm
 * init function
 */
void dsp_dtmf_goertzel_init(struct dsp *dsp)
{
	dsp->dtmf.size = 0;
	dsp->dtmf.lastwhat = '\0';
	dsp->dtmf.lastdigit = '\0';
	dsp->dtmf.count = 0;
}

/* check for hardware or software features
 */
void dsp_dtmf_hardware(struct dsp *dsp)
{
	int hardware = 1;

	if (!dsp->dtmf.enable)
		return;

	if (!dsp->features.hfc_dtmf)
		hardware = 0;

	/* check for volume change */
	if (dsp->tx_volume) {
		if (dsp_debug & DEBUG_DSP_DTMF)
			printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, "
			       "because tx_volume is changed\n",
			       __func__, dsp->name);
		hardware = 0;
	}
	if (dsp->rx_volume) {
		if (dsp_debug & DEBUG_DSP_DTMF)
			printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, "
			       "because rx_volume is changed\n",
			       __func__, dsp->name);
		hardware = 0;
	}
	/* check if encryption is enabled */
	if (dsp->bf_enable) {
		if (dsp_debug & DEBUG_DSP_DTMF)
			printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, "
			       "because encryption is enabled\n",
			       __func__, dsp->name);
		hardware = 0;
	}
	/* check if pipeline exists */
	if (dsp->pipeline.inuse) {
		if (dsp_debug & DEBUG_DSP_DTMF)
			printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, "
			       "because pipeline exists.\n",
			       __func__, dsp->name);
		hardware = 0;
	}

	dsp->dtmf.hardware = hardware;
	dsp->dtmf.software = !hardware;
}


/*************************************************************
 * calculate the coefficients of the given sample and decode *
 *************************************************************/

/* the given sample is decoded. if the sample is not long enough for a
 * complete frame, the decoding is finished and continued with the next
 * call of this function.
 *
 * the algorithm is very good for detection with a minimum of errors. i
 * tested it allot. it even works with very short tones (40ms). the only
 * disadvantage is, that it doesn't work good with different volumes of both
 * tones. this will happen, if accoustically coupled dialers are used.
 * it sometimes detects tones during speech, which is normal for decoders.
 * use sequences to given commands during calls.
 *
 * dtmf - points to a structure of the current dtmf state
 * spl and len - the sample
 * fmt - 0 = alaw, 1 = ulaw, 2 = coefficients from HFC DTMF hw-decoder
 */

u8
*dsp_dtmf_goertzel_decode(struct dsp *dsp, u8 *data, int len, int fmt)
{
	u8 what;
	int size;
	signed short *buf;
	s32 sk, sk1, sk2;
	int k, n, i;
	s32 *hfccoeff;
	s32 result[NCOEFF], tresh, treshl;
	int lowgroup, highgroup;
	s64 cos2pik_;

	dsp->dtmf.digits[0] = '\0';

	/* Note: The function will loop until the buffer has not enough samples
	 * left to decode a full frame.
	 */
again:
	/* convert samples */
	size = dsp->dtmf.size;
	buf = dsp->dtmf.buffer;
	switch (fmt) {
	case 0: /* alaw */
	case 1: /* ulaw */
		while (size < DSP_DTMF_NPOINTS && len) {
			buf[size++] = dsp_audio_law_to_s32[*data++];
			len--;
		}
		break;

	case 2: /* HFC coefficients */
	default:
		if (len < 64) {
			if (len > 0)
				printk(KERN_ERR "%s: coefficients have invalid "
				       "size. (is=%d < must=%d)\n",
				       __func__, len, 64);
			return dsp->dtmf.digits;
		}
		hfccoeff = (s32 *)data;
		for (k = 0; k < NCOEFF; k++) {
			sk2 = (*hfccoeff++) >> 4;
			sk = (*hfccoeff++) >> 4;
			if (sk > 32767 || sk < -32767 || sk2 > 32767
			    || sk2 < -32767)
				printk(KERN_WARNING
				       "DTMF-Detection overflow\n");
			/* compute |X(k)|**2 */
			result[k] =
				(sk * sk) -
				(((cos2pik[k] * sk) >> 15) * sk2) +
				(sk2 * sk2);
		}
		data += 64;
		len -= 64;
		goto coefficients;
		break;
	}
	dsp->dtmf.size = size;

	if (size < DSP_DTMF_NPOINTS)
		return dsp->dtmf.digits;

	dsp->dtmf.size = 0;

	/* now we have a full buffer of signed long samples - we do goertzel */
	for (k = 0; k < NCOEFF; k++) {
		sk = 0;
		sk1 = 0;
		sk2 = 0;
		buf = dsp->dtmf.buffer;
		cos2pik_ = cos2pik[k];
		for (n = 0; n < DSP_DTMF_NPOINTS; n++) {
			sk = ((cos2pik_ * sk1) >> 15) - sk2 + (*buf++);
			sk2 = sk1;
			sk1 = sk;
		}
		sk >>= 8;
		sk2 >>= 8;
		if (sk > 32767 || sk < -32767 || sk2 > 32767 || sk2 < -32767)
			printk(KERN_WARNING "DTMF-Detection overflow\n");
		/* compute |X(k)|**2 */
		result[k] =
			(sk * sk) -
			(((cos2pik[k] * sk) >> 15) * sk2) +
			(sk2 * sk2);
	}

	/* our (squared) coefficients have been calculated, we need to process
	 * them.
	 */
coefficients:
	tresh = 0;
	for (i = 0; i < NCOEFF; i++) {
		if (result[i] < 0)
			result[i] = 0;
		if (result[i] > dsp->dtmf.treshold) {
			if (result[i] > tresh)
				tresh = result[i];
		}
	}

	if (tresh == 0) {
		what = 0;
		goto storedigit;
	}

	if (dsp_debug & DEBUG_DSP_DTMFCOEFF) {
		s32 tresh_100 = tresh/100;

		if (tresh_100 == 0) {
			tresh_100 = 1;
			printk(KERN_DEBUG
				"tresh(%d) too small set tresh/100 to 1\n",
				tresh);
		}
		printk(KERN_DEBUG "a %3d %3d %3d %3d %3d %3d %3d %3d"
		       " tr:%3d r %3d %3d %3d %3d %3d %3d %3d %3d\n",
		       result[0] / 10000, result[1] / 10000, result[2] / 10000,
		       result[3] / 10000, result[4] / 10000, result[5] / 10000,
		       result[6] / 10000, result[7] / 10000, tresh / 10000,
		       result[0] / (tresh_100), result[1] / (tresh_100),
		       result[2] / (tresh_100), result[3] / (tresh_100),
		       result[4] / (tresh_100), result[5] / (tresh_100),
		       result[6] / (tresh_100), result[7] / (tresh_100));
	}

	/* calc digit (lowgroup/highgroup) */
	lowgroup = -1;
	highgroup = -1;
	treshl = tresh >> 3;  /* tones which are not on, must be below 9 dB */
	tresh = tresh >> 2;  /* touchtones must match within 6 dB */
	for (i = 0; i < NCOEFF; i++) {
		if (result[i] < treshl)
			continue;  /* ignore */
		if (result[i] < tresh) {
			lowgroup = -1;
			highgroup = -1;
			break;  /* noise in between */
		}
		/* good level found. This is allowed only one time per group */
		if (i < NCOEFF / 2) {
			/* lowgroup */
			if (lowgroup >= 0) {
				/* Bad. Another tone found. */
				lowgroup = -1;
				break;
			} else
				lowgroup = i;
		} else {
			/* higroup */
			if (highgroup >= 0) {
				/* Bad. Another tone found. */
				highgroup = -1;
				break;
			} else
				highgroup = i - (NCOEFF / 2);
		}
	}

	/* get digit or null */
	what = 0;
	if (lowgroup >= 0 && highgroup >= 0)
		what = dtmf_matrix[lowgroup][highgroup];

storedigit:
	if (what && (dsp_debug & DEBUG_DSP_DTMF))
		printk(KERN_DEBUG "DTMF what: %c\n", what);

	if (dsp->dtmf.lastwhat != what)
		dsp->dtmf.count = 0;

	/* the tone (or no tone) must remain 3 times without change */
	if (dsp->dtmf.count == 2) {
		if (dsp->dtmf.lastdigit != what) {
			dsp->dtmf.lastdigit = what;
			if (what) {
				if (dsp_debug & DEBUG_DSP_DTMF)
					printk(KERN_DEBUG "DTMF digit: %c\n",
					       what);
				if ((strlen(dsp->dtmf.digits) + 1)
				    < sizeof(dsp->dtmf.digits)) {
					dsp->dtmf.digits[strlen(
							dsp->dtmf.digits) + 1] = '\0';
					dsp->dtmf.digits[strlen(
							dsp->dtmf.digits)] = what;
				}
			}
		}
	} else
		dsp->dtmf.count++;

	dsp->dtmf.lastwhat = what;

	goto again;
}
