/***************************************************************************
*	NAME:  RESET.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	11/18/92		Original
***************************************************************************/
#include <dos.h>
#include <conio.h>

#include "forte.h"
#include "gf1proto.h"
#include "osproto.h"
#include "gf1hware.h"
#include "gf1os.h"

#include "ultraerr.h"

extern ULTRA_DATA _gf1_data;

/***************************************************************
 * This function performs a full reset & initialization on the 
 * UltraSound card.
 ***************************************************************/
int
UltraReset(int voices)
{
register int	v;
register int select,data_low,data_hi;

if ((voices < 14) || (voices > 32))
	return(BAD_NUM_OF_VOICES);

_gf1_data.voices = voices;
_gf1_data.timer_ctrl = 0;
_gf1_data.timer_mask = 0;

select = _gf1_data.reg_select;
data_low = _gf1_data.data_low;
data_hi = _gf1_data.data_hi;

/* Set these to zero so the they don't get summed in for voices that are */
/* not running. If their volumes are not at zero, whatever value they */
/* are pointing at, will get summed into the output. By setting that */
/* location to 0, that voice will have no contribution to the output */
/* (2 locations are done in case voice is set to 16 bits ... ) */
UltraPokeData(_gf1_data.base_port,0L,0);
UltraPokeData(_gf1_data.base_port,1L,0);

ENTER_CRITICAL;

/* Pull a reset on the GF1 */
	outp(select,MASTER_RESET);
	outp(data_hi,0x00);

/* Wait a little while ... */
	for (v=0;v<10;v++)
		gf1_delay();

/* Release Reset */
	outp(select,MASTER_RESET);
	outp(data_hi,GF1_MASTER_RESET);

/* Wait a little while ... */
	for (v=0;v<10;v++)
		gf1_delay();

/* Reset the MIDI port also */
	outp(_gf1_data.midi_control,MIDI_RESET);
	for (v=0;v<10;v++)
		gf1_delay();

	outp(_gf1_data.midi_control,0x00);

/* Clear all interrupts. */
	outp(select,DMA_CONTROL);
	outp(data_hi,0x00);
	outp(select,TIMER_CONTROL);
	outp(data_hi,0x00);
	outp(select,SAMPLE_CONTROL);
	outp(data_hi,0x00);

/* Set the number of active voices */
	outp(select,SET_VOICES);	
	outp(data_hi,(char)((voices-1) | 0xC0));

/* Clear interrupts on voices. */
/* Reading the status ports will clear the irqs. */
	(void)inp (_gf1_data.irq_status);	
	outp(select,DMA_CONTROL);
	(void)inp (data_hi);
	outp(select,SAMPLE_CONTROL);
	(void)inp (data_hi);
	outp(select,GET_IRQV);
	(void)inp (data_hi);
	
	for (v=0;v<voices;v++)
		{
		/* Select the proper voice */
		outp(_gf1_data.voice_select,v);

		/* Stop the voice and volume */
		outp(select,SET_CONTROL);
		outp(data_hi,VOICE_STOPPED|STOP_VOICE);
		outp(select,SET_VOLUME_CONTROL);
		outp(data_hi,VOLUME_STOPPED|STOP_VOLUME);
		
		gf1_delay(); /* Wait 4.8 micos. or more. */

		/* Initialize each voice specific registers. This is not */
		/* really necessary, but is nice for completeness sake .. */
		/* Each application will set up these to whatever values */
		/* it needs. */
		outp(select,SET_FREQUENCY);
		outpw(data_low,0x0400);
		outp(select,SET_START_HIGH);
		outpw(data_low,0);
		outp(select,SET_START_LOW);
 		outpw(data_low,0);
		outp(select,SET_END_HIGH);
		outpw(data_low,0);
		outp(select,SET_END_LOW);
		outpw(data_low,0);
		outp(select,SET_VOLUME_RATE);
		outp(data_hi,0x01);
		outp(select,SET_VOLUME_START);
		outp(data_hi,0x10);
		outp(select,SET_VOLUME_END);
		outp(data_hi,0xe0);
		outp(select,SET_VOLUME);
		outpw(data_low,0x0000);

		outp(select,SET_ACC_HIGH);
		outpw(data_low,0);
		outp(select,SET_ACC_LOW);
		outpw(data_low,0);
		outp(select,SET_BALANCE);
		outp(data_hi,0x07);
		}

	(void)inp (_gf1_data.irq_status);	
	outp(select,DMA_CONTROL);
	(void)inp (data_hi);
	outp(select,SAMPLE_CONTROL);
	(void)inp (data_hi);
	outp(select,GET_IRQV);
	(void)inp (data_hi);
	
	/* Set up GF1 Chip for interrupts & enable DACs. */
	outp(select,MASTER_RESET);
	outp(data_hi,GF1_MASTER_RESET|GF1_OUTPUT_ENABLE|GF1_MASTER_IRQ);

LEAVE_CRITICAL;

return(ULTRA_OK);
}


