/***************************************************************************
*	NAME:  EXAMPLE.C
**	COPYRIGHT:
**	"Copyright (c) 1992, by FORTE
**
**       "This software is furnished under a license and may be used,
**       copied, or disclosed only in accordance with the terms of such
**       license and with the inclusion of the above copyright notice.
**       This software or any other copies thereof may not be provided or
**       otherwise made available to any other person. No title to and
**       ownership of the software is hereby transfered."
****************************************************************************
*  CREATION DATE: 11/18/92
*--------------------------------------------------------------------------*
*     VERSION	DATE	   NAME		DESCRIPTION
*>	1.0	05/01/93		Original
***************************************************************************/

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <io.h> 
#include <dos.h>
#include <malloc.h>
#include <string.h>

#include "forte.h"

#ifdef PHAR_LAP
#include <pharlap.h>
#endif

#define REC_SIZE (unsigned int)((63*1024))

#ifdef WATCOMC
#define close _dos_close
#endif

#ifdef MSOFTC
#define close _dos_close
#endif

#ifdef METAWARE 
#define close _close
#endif

#include "gf1proto.h"
#include "extern.h"
#include "ultraerr.h"

PFV UltraTimer2Handler(PFV handler);
PFV UltraTimer1Handler(PFV handler);
int UltraGetCfg(ULTRA_CFG *config);

int timer1_val=1;
int timer2_val=1;
int count1=0;
int count2=0;

void 
HandleTimer1(void)
{
count1++;
}

void 
HandleTimer2(void)
{
count2++;
}

void
main()
{
char filename[80];
char temp_char[10];
unsigned char control;
unsigned char rec_control;
void *data_ptr;
void *vdata_ptr;
int fd;
int dram_len;
int temp;
int done;
int select;
int voice_num = 0;		/* examples use voice #0 */
unsigned int val;
unsigned int temp_val;
unsigned long dram_loc;
unsigned long begin,start_loop,end_loop;
unsigned long frequency;
unsigned long pos;
ULTRA_CFG config;
/* Get the ULTRASND environment string parameters */
UltraGetCfg(&config);
#ifdef PHAR_LAP
	unsigned short nParagraphs;		// set before call
	unsigned short paragraphAddress;
	unsigned short largestMemoryBlock;
	unsigned long physicalAddress;
#endif

if (UltraProbe(config.base_port) == NO_ULTRA)
	{
	printf("No card found\n");
	exit(-1);
	}

if (UltraOpen(&config,14) == NO_ULTRA)
	{
	printf("No card found\n");
	exit(-1);
	}

dram_len = UltraSizeDram();

printf("\nFound %dK of Dram\n",dram_len);

/* Grab the 80 microsecond timer handler */
UltraTimer1Handler(HandleTimer1);

/* Grab the 320 microsecond timer handler */
UltraTimer2Handler(HandleTimer2);

printf("\nExample program for UltraSound Audio Card\n");
printf("=========================================\n\n");

done = FALSE;

while (!done)
	{
	printf("0  - Exit\n");
	printf("1  - Reset UltraSound\n");
	printf("2  - Download a sample\n");
	printf("3  - Note on\n");
	printf("4  - Note off\n");
	printf("5  - Set Playback/Record rate\n");
	printf("6  - Set Balance\n");
	printf("7  - Set Volume\n");
	printf("8  - Set Channel to use\n");
	printf("9  - Read voice's absolute position\n");
	printf("10 - Ramp volume\n");
	printf("11 - Demo timer #1 (80 usec)\n");
	printf("12 - Demo timer #2 (320 usec)\n");
	printf("13 - Demo recording\n");

	while (TRUE)
		{
		printf("\nEnter Selection : ");
		val = scanf("%d",&select);
		if (val != 0)
			break;
		else
			{
			printf("\nBad Selection\n");
			scanf("%*s");	/* eat the bad string */
			}
		}

	switch (select)
		{
		case 0:
			done = TRUE;
			break;
		case 1:
			temp = UltraGetOutput();
			UltraDisableOutput();
			UltraReset(32);
			/* Re-Init some voice parms to defaults ... */
			UltraSetLinearVolume(voice_num,256);
			UltraSetFrequency(voice_num,22050L);
			UltraSetBalance(voice_num,7);
			if (temp)
				UltraEnableOutput();
			break;
		case 2:		/* download a sample to DRAM */
			control = 0;
			printf("Filename to get data from ? ");
			scanf("%s",filename);
#ifdef BORLANDC
			fd = _open(filename,O_RDONLY|O_BINARY);
#else
			_dos_open(filename,O_RDONLY|O_BINARY,&fd);
#endif
			if (fd == -1)
				{
				printf("Can't open file\n");
				break;
				}
			printf("Amount to send down (bytes) ? ");
			scanf("%u",&val);
#ifdef PHAR_LAP
/*************************************************************************
 NOTE: This section is for getting a physical addr to DMA buffer. It
         DOES NOT WORK !!!! Please contact Forte if you can get it to work
**************************************************************************/

	nParagraphs = (val+16)>>4;
	_dx_real_alloc(nParagraphs, &paragraphAddress, &largestMemoryBlock);
	physicalAddress = paragraphAddress << 4;
	data_ptr = (void *)physicalAddress;
//			if(_dx_real_alloc(val,(USHORT*)&data_ptr,(USHORT*)&vdata_ptr) != 0)
//				data_ptr = NULL;
#else
			data_ptr = malloc(val);
#endif
			if (data_ptr == NULL)
				{
				printf("\n\nError allocating DMA buffer\n");
				close(fd);
				break;
				}
#ifdef BORLANDC
			temp_val = _read(fd,data_ptr,val);
#else
			_dos_read(fd,(_Far void *)data_ptr,val,&temp_val);
#endif
			if (temp_val != val)
				{
				printf("Read failure %d\n",temp_val);
				free(data_ptr);
				close(fd);
				break;
				}
			printf("Ultra DRAM location to put data ? ");
			scanf("%ld",&dram_loc);

			printf("8 bit (y/n) ? ");
			scanf("%s",temp_char);
			strupr(temp_char);
			if (strcmp(temp_char,"Y") == 0)
				{
				control |= DMA_8;
				}
			else
				{
				control |= DMA_16;
				}
			printf("Is it in twos compliment form ? ");
			scanf("%s",temp_char);
			strupr(temp_char);
			if (strcmp(temp_char,"Y") == 0)
				{
				control |= DMA_NO_CVT;
				}
			else
				{
				control |= DMA_CVT_2;
				}

			UltraDownload(data_ptr,control,dram_loc,val,TRUE);
			free(data_ptr);
			close(fd);
			break;
		case 3:		/* Note on */
			printf("Begining location ? ");
			scanf("%ld",&begin);
			printf("Loop start location ? ");
			scanf("%ld",&start_loop);
			printf("End location ? ");
			scanf("%ld",&end_loop);
			printf("Loop type (0=none,1=uni-direct,2=bi_direct) ? ");
			scanf("%d",&temp_val);
			control = 0;
			if (temp_val > 2)
				{
				printf("Bad loop type\n");
				break;
				}
			switch (temp_val)
				{
				case 0:		/* no looping */
					break;
				case 1:		/* uni-directional looping */
					control |= 0x08;
					break;
				case 2:		/* bi-directional looping */
					control |= 0x08;
					control |= 0x10;
					break;
				}
			printf("8 bit (y/n) ? ");
			scanf("%s",temp_char);
			strupr(temp_char);
			if (strcmp(temp_char,"Y") != 0)
				{
				control |= 0x04;
				}
			printf("Frequency (in hertz) = : ");
			scanf("%ld",&frequency);
			UltraVoiceOn(voice_num,begin,start_loop,end_loop,control,frequency);
			break;
		case 4:		/* Note off */
			/* This could be used to change the end point and let the sample */
			/* stop at end (sampled decay.... ) */
			/* UltraSetVoiceEnd(voice_num,end_loop); */
			UltraVoiceOff(voice_num,FALSE);
			break;
		case 5:		/* Set playback rate */
			printf("New Frequency (in hertz) = : ");
			scanf("%ld",&frequency);
			printf("\n");

			UltraSetFrequency(voice_num,frequency);
			break;
		case 6:		/* Set balance */
			printf("New Balance = (0-15) : ");
			scanf("%d",&val);
			printf("\n");

			UltraSetBalance(voice_num,val);
			break;
		case 7:		/* Set volume */
			printf("New Volume = (0-511) : ");
			scanf("%d",&val);
			printf("\n");

			UltraSetLinearVolume(voice_num,val);
			break;
		case 8:
			printf("Channel to use ? ");
			scanf("%d",&voice_num);
			break;
		case 9:
			printf("Voice #%d position (hit a key to stop)\n",voice_num);
			while (!kbhit())
				{
				pos = UltraReadVoice(voice_num);
				printf("\r%ld        ",pos);
				}
			getch();
			printf("\n\n");
			break;
		case 10:
			printf("Start Volume = (0-511) : ");
			scanf("%d",&val);
			printf("End Volume = (0-511) : ");
			scanf("%d",&temp_val);
			printf("Milliseconds to Ramp Volume : ");
			scanf("%ld",&pos);
			printf("\n");
			UltraRampLinearVolume(voice_num,val,temp_val,pos,0x18);
			break;
		case 11:
			count1 = 0;
			printf("Time value (1-255) : ");
			scanf("%d",&timer1_val);
			printf("Press any key to halt\n");
			UltraStartTimer(1,timer1_val); 
			while (!kbhit())
				;
			UltraStopTimer(1);
			printf("Count = %d\n",count1);
			break;
		case 12:
			count2 = 0;
			printf("Time value (1-255) : ");
			scanf("%d",&timer2_val);
			printf("Press any key to halt\n");
			UltraStartTimer(2,timer2_val); 
			while (!kbhit())
				;
			UltraStopTimer(2);
			printf("Count = %d\n",count2);
			break;
		case 13:
			rec_control = 0;
			control = 0;
			printf("Frequency (in hertz) = : ");
			scanf("%ld",&frequency);
			UltraSetRecordFrequency(frequency);
			UltraSetFrequency(voice_num,frequency);
			data_ptr = malloc(REC_SIZE);
			UltraMemAlloc((unsigned long)REC_SIZE,(unsigned long far *)&dram_loc);

			UltraEnableLineIn();
			UltraEnableMicIn(); 
			UltraEnableOutput();

			while(TRUE)
				{
				printf("Hit a key to begin recording ....(ESC to quit)");
				while (!kbhit())
					;
				printf("\n");
				if (getch() == 0x1b)
					break;

				UltraRecordData(data_ptr,rec_control,REC_SIZE,FALSE,FALSE);
				while (UltraRecordDmaBusy())
					{
					val = UltraReadRecordPosition();
					printf("%05u\r",val);
					}
				printf("\n");

				printf("Hit a key to begin playback ....(ESC to quit)");
				while (!kbhit())
					;
				printf("\n");
				if (getch() == 0x1b)
					break;

				/* start download with no wait. Then start voice. */
				UltraDownload(data_ptr,control,dram_loc,REC_SIZE,TRUE);
				UltraStartVoice(voice_num,dram_loc,dram_loc,
						dram_loc+REC_SIZE-1,0);

				/* If this check is ommitted, it will begin recording */
				/* while it is still downloading & playing ... Try it ... */

				while (!UltraVoiceStopped(voice_num))
					{
					pos = UltraReadVoice(voice_num);
					printf("%05ld\r",pos-dram_loc);
					}
				printf("\n");
				}
			free(data_ptr);
			UltraMemFree((unsigned long)REC_SIZE,dram_loc);
			UltraDisableLineIn();
			UltraDisableMicIn();
			break;
		default:
			break;
		}
	}

/* Shut sound down & re-init hardware ... */
UltraClose();
}

