/***************************************************************************
*	NAME:  SAMPLE16.C
**	COPYRIGHT:
**	"Copyright (c) 1994, 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: 01/01/94
*--------------------------------------------------------------------------*
*     VERSION	DATE	   NAME		DESCRIPTION
*>	1.0	01/01/94		Original
***************************************************************************/

#include <stdio.h>
#include <dos.h>
#include <conio.h>

#include "forte.h"
#include "gf1proto.h"
#include "osproto.h"
#include "proto16.h"
#include "gf1hware.h"
#include "codec.h"
#include "gf1os.h"
#include "codecos.h"
#include "ultraerr.h"
#include "dma.h"	/* Hardware defs for PC's dma controllers */

extern DMA_ENTRY _gf1_dma[]; /* Structure that holds data on PC's dma chan */
extern ULTRA_DATA _gf1_data;
extern ULTRA16_DATA _codec_data;
extern IMAGE16 _image_codec;

int
Ultra16RecordDmaBusy()
{
return(_gf1_dma[_codec_data.rec_chan-1].flags & DMA_PENDING);
}

void
Ultra16WaitRecordDma()
{
	_codec_data.flags &= ~ADC_DMA_NOWAIT;

	ENTER_CRITICAL ;

	while (_codec_data.flags & ADC_DMA_BUSY)	/* wait for irq to clear this */
		{
		}

	LEAVE_CRITICAL ;
}

int
Ultra16PrimeRecord(pc_ptr,size,repeat)
void far *pc_ptr;
unsigned int size;
int repeat;
{
int mode;

if (repeat)
	mode = INDEF_READ;
else
	mode = READ_DMA;

/* Make sure the channel is not busy (recording or playback ... )*/
return(PrimeDma(pc_ptr,mode,size,_codec_data.rec_chan));
}

void
Ultra16StartRecordDma(control)
unsigned char control;
{
ENTER_CRITICAL;

/* kick off codec here ... */
outp(_codec_data.addr,CODEC_MCE|IFACE_CTRL);
_image_codec.ic |= CAPTURE_ENABLE;
outp(_codec_data.data,_image_codec.ic);
outp(_codec_data.addr,IFACE_CTRL);

LEAVE_CRITICAL;
}

void
Ultra16StopRecordDma()
{
DMA_ENTRY *tdma;

ENTER_CRITICAL;

outp(_codec_data.addr,CODEC_MCE|IFACE_CTRL);
_image_codec.ic &= ~CAPTURE_ENABLE;
outp(_codec_data.data,_image_codec.ic);
outp(_codec_data.addr,IFACE_CTRL);

tdma  = &_gf1_dma[_codec_data.rec_chan-1];		/* point to this dma data */
outp(tdma->single,tdma->dma_disable);		/* disable chan */
tdma->flags &= ~DMA_PENDING;

/* Clear flag that irq handler clears when the xfer is complete */
_codec_data.flags &= ~ADC_DMA_BUSY;

LEAVE_CRITICAL;
}


int
Ultra16GoRecord(control)
unsigned char control;
{
DMA_ENTRY *tdma;

tdma  = &_gf1_dma[_codec_data.rec_chan-1];		/* point to this dma data */

/* Set flag that irq handler clears when the xfer is complete */
_codec_data.flags |= ADC_DMA_BUSY;

/* Now tell CODEC to start xfer ... */
tdma->cur_control = control;

Ultra16StartRecordDma(control);

return(ULTRA_OK);
}

int
Ultra16RecordData(pc_ptr,control,size,wait,repeat)
void far *pc_ptr;
unsigned char control;
unsigned int size;
int wait;
int repeat;
{
int ret;

if (_codec_data.type == 1)
	{
	if (_codec_data.rec_chan >=4)
		{
ENTER_CRITICAL;
		outp(_gf1_data.base_port+0x106,_codec_data.setup & ~0x10);
		outp(_gf1_data.base_port+0x106,_codec_data.setup);
LEAVE_CRITICAL;
		}
	}

if ((ret=Ultra16PrimeRecord(pc_ptr,size,repeat)) != ULTRA_OK)
	return(ret);

/* set up the counts ... */
Ultra16ProgRecCnt(size);

Ultra16GoRecord(control);

/* if required, wait till dma is done ... */
if (wait)
	Ultra16WaitRecordDma();
else
	_codec_data.flags |= ADC_DMA_NOWAIT;

return(ULTRA_OK);
}

unsigned int
Ultra16ReadRecordPosition()
{
DMA_ENTRY *tdma;
unsigned int actual_dma;
unsigned int this_size;
unsigned int total_size;

	tdma  = &_gf1_dma[_codec_data.rec_chan-1]; /* point to this dma data */

	actual_dma = GetRecordDmaPos(_codec_data.rec_chan);

	/* Since it counts backwards, subtract this from size of transfer */
	this_size = tdma->cur_size - actual_dma;

	/* Now add in the amount sent (in case it crosses page) */
	total_size = tdma->amnt_sent + this_size;

	if ( _codec_data.rec_chan >= 4)
		total_size <<= 1;

return(total_size);
}

int
Start_Recording(pc_ptr,size)
void far *pc_ptr;
unsigned int size;
{
unsigned char control=0;

return(Ultra16RecordData(pc_ptr,control,size,FALSE,TRUE));

}

void
Ultra16ProgRecCnt(size)
unsigned int size;
{
unsigned char temp;
unsigned int psize;

psize = size;

/* if in MODE 2 && DUAL DMA */
// if ((_image_codec.mi & CODEC_MODE2) && !(_image_codec.ic & SINGLE_DMA))
if (_image_codec.mi & CODEC_MODE2)
	{

	temp = _image_codec.cdfr & 0xE0;	/* isolate the format bits */
	switch (temp)
		{
		case 0x40:		/* 16 bit litle endian */
		case 0xC0:		/* 16 bit big endian */
			size >>= 1;
			break;
		case 0xA0:		/* 16 bit ADPCM */
			size >>= 2;
			break;
		}

	if (_image_codec.cdfr & TYPE_STEREO && temp != 0xA0) // not if ADPCM
		size >>= 1;

	size--;
ENTER_CRITICAL;
	outp(_codec_data.addr,REC_LWR_CNT);
	outp(_codec_data.data,(char)size);
	outp(_codec_data.addr,REC_UPR_CNT);
	outp(_codec_data.data,(char)(size>>8));
LEAVE_CRITICAL;
	}
else
	{
	Ultra16ProgPlayCnt(psize);
	}
}

