/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1991 by Olaf 'Olsen' Barthel & MXM
 *
 *	Touch-tone period & cycle values are
 *
 *	(C) Copyright 1989 by Commodore-Amiga, Inc.
 *
 *	Name .....: ToneDial.c
 *	Created ..: Wednesday 03-Jul-91 10:38
 *	Revision .: 0
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	03-Jul-91       Olsen           Created this file!
 *
 * $Revision Header ********************************************************/

#include "TermGlobal.h"

	/* Audio device control. */

STATIC struct IOAudio	*Audio,
			*Audio1,
			*Audio2;

	/* A couple of reply ports. */

STATIC struct MsgPort	*AudioPort,
			*Audio1Port,
			*Audio2Port;

	/* Channel allocation scheme is as follow:
	 *
	 *	- allocate two channels either on the right or
	 *	  the left side.
	 *
	 *	- if this fails, allocate two different stereo
	 *	  channels.
	 */

STATIC UBYTE Channels[] =
{
	LEFT0F  | LEFT1F,
	RIGHT0F | RIGHT1F,
	LEFT0F  | RIGHT1F,
	RIGHT0F | LEFT1F
};

	/* Cheapo square wave. */

STATIC BYTE __chip SquareWave[8] =
{
	0,127,127,0,0,-127,-127,0
};

	/* Touch tone periods for NTSC machines. */

STATIC UWORD NTSC_Periods[16][2] = 
{
	{ 475,335 },	/* 0 */
	{ 642,370 },	/* 1 */
	{ 642,335 },	/* 2 */
	{ 642,303 },	/* 3 */
	{ 581,370 },	/* 4 */
	{ 581,335 },	/* 5 */
	{ 581,303 },	/* 6 */
	{ 525,370 },	/* 7 */
	{ 525,335 },	/* 8 */
	{ 525,303 },	/* 9 */
	{ 475,370 },	/* * */
	{ 475,303 },	/* # */
	{ 642,274 },	/* A */
	{ 581,274 },	/* B */
	{ 525,274 },	/* C */
	{ 475,274 },	/* D */
};

	/* Touch tone periods for PAL machines. */

STATIC UWORD PAL_Periods[16][2] = 
{
	{ 471,332 },	/* 0 */
	{ 636,367 },	/* 1 */
	{ 636,332 },	/* 2 */
	{ 636,300 },	/* 3 */
	{ 576,367 },	/* 4 */
	{ 576,332 },	/* 5 */
	{ 576,300 },	/* 6 */
	{ 520,367 },	/* 7 */
	{ 520,332 },	/* 8 */
	{ 520,300 },	/* 9 */
	{ 471,367 },	/* * */
	{ 471,300 },	/* # */
	{ 636,271 },	/* A */
	{ 576,271 },	/* B */
	{ 520,271 },	/* C */
	{ 471,271 }	/* D */
};

	/* Length of each tone given in audio cycles. */

UWORD Cycles[16][2] = 
{
	{ 106,150 },	/* 0 */
	{  96,166 },	/* 1 */
	{ 106,204 },	/* 2 */
	{ 118,250 },	/* 3 */
	{  96,150 },	/* 4 */
	{ 106,184 },	/* 5 */
	{ 118,226 },	/* 6 */
	{  96,136 },	/* 7 */
	{ 106,166 },	/* 8 */
	{ 118,204 },	/* 9 */
	{  96,124 },	/* * */
	{ 118,186 },	/* # */
	{ 130,304 },	/* A */
	{ 130,276 },	/* B */
	{ 130,250 },	/* C */
	{ 130,226 }	/* D */
};

	/* The tone codes we know. */

UBYTE *Codes = "0123456789*#ABCD";

	/* DeleteTone():
	 *
	 *	Free the resources allocated for touch-tone dialing.
	 */

VOID
DeleteTone()
{
	if(Audio2)
	{
		FreeVec(Audio2);

		Audio2 = NULL;
	}

	if(Audio2Port)
	{
		DeleteMsgPort(Audio2Port);

		Audio2Port = NULL;
	}

	if(Audio1)
	{
		FreeVec(Audio1);

		Audio1 = NULL;
	}

	if(Audio1Port)
	{
		DeleteMsgPort(Audio1Port);

		Audio1Port = NULL;
	}

	if(Audio)
	{
		if(Audio -> ioa_Request . io_Device)
			CloseDevice(Audio);

		DeleteIORequest(Audio);

		Audio = NULL;
	}

	if(AudioPort)
	{
		DeleteMsgPort(AudioPort);

		AudioPort = NULL;
	}
}

	/* CreateTone():
	 *
	 *	Allocate the resources required for touch-tone dialing.
	 */

STATIC BYTE
CreateTone()
{
	if(AudioPort = CreateMsgPort())
	{
		if(Audio = (struct IOAudio *)CreateIORequest(AudioPort,sizeof(struct IOAudio)))
		{
			Audio -> ioa_Request . io_Message . mn_Node . ln_Pri	= 10;
			Audio -> ioa_Data					= Channels;
			Audio -> ioa_Length					= sizeof(Channels);

			if(!OpenDevice(AUDIONAME,0,Audio,0))
			{
				Audio -> ioa_Request . io_Command	= CMD_WRITE;
				Audio -> ioa_Request . io_Flags		= ADIOF_PERVOL;
				Audio -> ioa_Data			= SquareWave;
				Audio -> ioa_Length			= 8;
				Audio -> ioa_Volume			= 32;

				if(Audio1Port = CreateMsgPort())
				{
					if(Audio1 = (struct IOAudio *)AllocVec(sizeof(struct IOAudio),MEMF_PUBLIC))
					{
						CopyMem(Audio,Audio1,sizeof(struct IOAudio));

						Audio1 -> ioa_Request . io_Message . mn_ReplyPort	= Audio1Port;
						Audio1 -> ioa_Request . io_Unit				= (APTR)((ULONG)Audio -> ioa_Request . io_Unit & (DMAF_AUD0|DMAF_AUD1));

						if(Audio2Port = CreateMsgPort())
						{
							if(Audio2 = (struct IOAudio *)AllocVec(sizeof(struct IOAudio),MEMF_PUBLIC))
							{
								CopyMem(Audio,Audio2,sizeof(struct IOAudio));

								Audio2 -> ioa_Request . io_Message . mn_ReplyPort	= Audio2Port;
								Audio2 -> ioa_Request . io_Unit				= (APTR)((ULONG)Audio -> ioa_Request . io_Unit & (DMAF_AUD2|DMAF_AUD3));

								return(TRUE);
							}
						}
					}
				}
			}
		}

		DeleteTone();
	}

	return(FALSE);
}

	/* ToneDial(UBYTE *Number):
	 *
	 *	Dial a number using touch-tone coding, produce the
	 *	sounds using the Amiga audio hardware.
	 */

BYTE
ToneDial(UBYTE *Number)
{
	WORD i,j;

		/* Resources ready? */

	if(!Audio)
	{
		if(!CreateTone())
			return(FALSE);
	}

		/* Check TV system (i.e. crystal frequency). */

	if(GfxBase -> DisplayFlags & PAL)
	{
		for(i = 0 ; i < strlen(Number) ; i++)
		{
			for(j = 0 ; j < 16 ; j++)
			{
				if(ToUpper(Number[i]) == Codes[j])
				{
					Audio1 -> ioa_Cycles	= Cycles[j][0];
					Audio1 -> ioa_Period	= PAL_Periods[j][0];

					Audio2 -> ioa_Period	= PAL_Periods[j][1];
					Audio2 -> ioa_Cycles	= Cycles[j][1];

					BeginIO(Audio1);
					BeginIO(Audio2);

					WaitIO(Audio1);
					WaitIO(Audio2);

					Delay(8);

					break;
				}
			}
		}
	}
	else
	{
		for(i = 0 ; i < strlen(Number) ; i++)
		{
			for(j = 0 ; j < 16 ; j++)
			{
				if(Number[i] == Codes[j])
				{
					Audio1 -> ioa_Cycles	= Cycles[j][0];
					Audio1 -> ioa_Period	= NTSC_Periods[j][0];

					Audio2 -> ioa_Cycles	= Cycles[j][1];
					Audio2 -> ioa_Period	= NTSC_Periods[j][1];

					BeginIO(Audio1);
					BeginIO(Audio2);

					WaitIO(Audio1);
					WaitIO(Audio2);

					Delay(8);

					break;
				}
			}
		}
	}

	return(TRUE);
}
