#include <dos.h>
#include "iwdefs.h"
#include "iwprotos.h"
extern IWAVE iw;
//########################################################################
//
// FILE   : iwcodec.c
//
// REMARKS: This file contains the definitions of DDK functions in
//          the CODEC family.
//
// UPDATE: 5/30/95
//
//########################################################################
//
// FUNTION : IwaveCodecMode
//
// PROFILE: This function allows to switch between the diferent modes
//          of codec operation. The following calls illustrate the
//          usage: IwaveCodecMode(CODEC_MODE3) puts the codec in mode 3.
//
//########################################################################
void IwaveCodecMode(BYTE mode)
{
 BYTE reg;

 ENTER_CRITICAL;
 reg=_peek(iw.pcodar)&0xE0;
 _poke(iw.pcodar,reg|_CMODEI);      // select CMODEI
 _poke(iw.cdatap,mode);
 LEAVE_CRITICAL;
 iw.cmode=mode;
}
//########################################################################
//
// FUNTION : IwaveLineMute
//
// PROFILE: This function allows the calling program to mute or unmute
//          the following inputs or outputs to/from the InterWave IC:
//
//          - the AUX1/Synth line input (left and right)
//          - the AUX2 line input
//          - the left and right line outputs
//          - the left and right line inputs
//
//          The first argument is a boolean type of argument. Set it to
//          ON to mute or OFF to unmute. The second argument is an index
//         to a register. Set it to any of the following:
//
//          - _CLAX1I or LEFT_AUX1_INPUT  (All modes)
//          - _CRAX1I or RIGHT_AUX1_INPUT
//          - _CLAX2I or LEFT_AUX2_INPUT  (All modes)
//          - _CRAX2I or RIGHT_AUX2_INPUT
//          - _CLOAI or LEFT_LINE_OUT     (Mode 3 only)
//          - _CROAI or RIGHT_LINE_OUT
//          - _CLMICI or LEFT_MIC_IN      (Mode 3 only)
//          - _CRMICI or RIGHT_MIC_IN
//          - _CLLICI or LEFT_LINE_IN     (Modes 2 & 3)
//          - _CRLICI or RIGHT_LINE_IN
//          - _CLDACI or LEFT_DAC         (All modes)
//          - _CRDACI or RIGHT_DAC
//
//########################################################################
void IwaveLineMute(BYTE mute, BYTE inx)
{
  BYTE reg;

	ENTER_CRITICAL;
   reg=_peek(iw.pcodar)&0xE0;
	_poke(iw.pcodar,reg|inx);                             // select register
	if (mute==ON)
		 _poke(iw.cdatap,(BYTE)(_peek(iw.cdatap)|0x08));   // mute
	else
		 _poke(iw.cdatap,(BYTE)(_peek(iw.cdatap)&0x7F));   // unmute
	LEAVE_CRITICAL;
}
//########################################################################
//
// FUNTION : IwaveMonoMute
//
// PROFILE: This function allows the calling program to mute or unmute
//          the mono input or output to/from the InterWave IC via
//          CMONOI[7:6].
//
//          The first argument should always be set to either ON or OFF.
//          The second argument should be set to either MONO_OUTPUT or
//          MONO_INPUT.
//
//########################################################################
void IwaveMonoMute(BYTE state, BYTE io)
{
  BYTE reg;

  ENTER_CRITICAL;
  reg=_peek(iw.pcodar)&0xE0;
  _poke(iw.pcodar,reg|0x1A);                          // select register
  if (state==ON)
		_poke(iw.cdatap,(BYTE)(_peek(iw.cdatap)|io));   // mute
  else
	  _poke(iw.cdatap,(BYTE)(_peek(iw.cdatap)&~io));   // unmute 
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNTION : IwaveMonoLevel
//
// PROFILE: This function allows the calling program to set the attenuation
//          level for the mono input via CMONOI[3:0].
//
//          The first argument should always be set to a number in the
//          range 0-15 for attenuation from 0dB to 45dB in steps of 3 dB.
//
//########################################################################
void IwaveMonoLevel(BYTE level)
{
   BYTE reg;
//
	ENTER_CRITICAL;
	reg=_peek(iw.pcodar)&0xE0;
	_poke(iw.pcodar,reg|0x1A);
	_poke(iw.cdatap,(BYTE)((_peek(iw.cdatap)&0xF0)|level)); // set atten
	LEAVE_CRITICAL;
}
//########################################################################
//
// FUNTION : IwaveInputSource
//
// PROFILE: This function allows the calling program to select among any
//          of several possible sources to the ADC's. The possible input
//          sources and their corresponding symbolic constants are:
//          - Line        (LINE_IN)
//          - Aux1        (AUX1_IN)
//          - Microphone  (MIC_IN)
//          - Mixer       (MIX_IN)
//
//          Set the first argument to either LEFT_SOURCE or RIGHT_SOURCE.
//          Always use the symbolic contants for the arguments.
//
//########################################################################
void IwaveInputSource(BYTE index, BYTE source)
{
	BYTE reg;

	ENTER_CRITICAL;
   reg=_peek(iw.pcodar)&0xE0;
	_poke(iw.pcodar,reg|index);     //select register CLICI or CRICI
	reg=_peek(iw.cdatap)&~MIX_IN;
	source&=MIX_IN;
	_poke(iw.cdatap,(BYTE)(reg|source));
	LEAVE_CRITICAL;
}
//########################################################################
//
// FUNTION : IwaveInputGain
//
// PROFILE: This function allows the calling program to set a gain level
//          for the left and right sources (CLICI[7:6] or CRICI[7:6]).
//          The gain can be anywhere in 0dB-22.5dB. The gain argument
//          can be a value between 0-15. Set the first argument to
//          either LEFT_SOURCE (or _CLICI) or RIGHT_SOURCE (or _CRICI).
//
//########################################################################
void IwaveInputGain(BYTE index, BYTE gain)
{
  BYTE reg;
//
  gain&=0x0F;
  ENTER_CRITICAL;
  reg=_peek(iw.pcodar)&0xE0;
  _poke(iw.pcodar,reg|index);
  _poke(iw.cdatap,(BYTE)((_peek(iw.cdatap)&0xE0)|gain));
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNTION : IwaveLineLevel
//
// PROFILE: This function allows the calling program to control the level
//          of attenuation or gain for inputs or outputs to or from the
//          InterWave IC:
//
//          - the AUX1/Synth line input (left and right)
//          - the AUX2 line input (left and right)
//          - the left and right line outputs
//          - the left and right line inputs
//
//          The first argument is a boolean type of argument. Set it to
//          the desired level of gain or attenuation. The second argument
//          is an index to a register. Set it to any of the following:
//
//          - _CLAX1I or LEFT_AUX1_INPUT    (All modes)
//          - _CRAX1I or RIGHT_AUX1_INPUT
//          - _CLAX2I or LEFT_AUX2_INPUT    (All modes)
//          - _CRAX2I or RIGHT_AUX2_INPUT
//          - _CLOAI or LEFT_LINE_OUT       (Mode 3 only)
//          - _CROAI or RIGHT_LINE_OUT
//          - _CLMICI or LEFT_MIC_IN        (Mode 3 only)
//          - _CRMICI or RIGHT_MIC_IN
//          - _CLLICI or LEFT_LINE_IN       (Modes 2 and 3)
//          - _CRLICI or RIGHT_LINE_IN
//
//########################################################################
void IwaveLineLevel(BYTE level, BYTE index)
{
  BYTE reg;
//
	level&=0x1F;

	ENTER_CRITICAL;
   reg=_peek(iw.pcodar)&0xE0;
	_poke(iw.pcodar,reg|index);                             /* select register */
	_poke(iw.cdatap,(BYTE)((_peek(iw.cdatap)&0x80)|level)); /* set level */
	LEAVE_CRITICAL;
}
//########################################################################
//
// FUNTION : IwaveDacAtten
//
// PROFILE: This function allows the calling program to control the level
//          of attenuation to the left or right DACs. Set the second
//          argument to either LEFT_DAC or RIGHT_DAC. The first argument
//          is a number between 0 and 63.
//
//########################################################################
void IwaveDacAtten(BYTE level, BYTE index)
{
  BYTE reg;
//
	level&=0x3F;
	ENTER_CRITICAL;
   reg=_peek(iw.pcodar)&0xE0;
	_poke(iw.pcodar,reg|index);                             // select register
	_poke(iw.cdatap,(BYTE)((_peek(iw.cdatap)&0x80)|level)); // set atten
	LEAVE_CRITICAL;
}
//########################################################################
//
// FUNTION : IwaveSetFrequency
//
// PROFILE: This function allows the calling program to set the either
//          the playback or record sample frequency. The caller specifies
//          the frequency in hertz and the closest frequency is set in
//          either register CPDFI or CRDFI.
//
//########################################################################
void IwaveSetFrequency(BYTE index, WORD freq)
{
  BYTE var, reg;
  CODEC_FREQ codec_freq[14] = {
	{5, 0x00|XTAL2},{6, 0x0E|XTAL2},
	{8, 0x00|XTAL1},{9, 0x0E|XTAL1},
	{11,0x02|XTAL2},{16,0x02|XTAL1},
	{18,0x04|XTAL2},{22,0x06|XTAL2},
	{27,0x04|XTAL1},{32,0x06|XTAL1},
	{33,0x0C|XTAL2},{37,0x08|XTAL2},
	{44,0x0A|XTAL2},{48,0x0C|XTAL1}};

  freq=freq/1000;
  if (freq>48) freq=48;

  for (var=0; var<14; var++)         /* select closest frequency */
	  if (freq<=codec_freq[var].freq)
			break;
  if (iw.cmode==CODEC_MODE1||iw.cmode==CODEC_MODE2)
      index=_CPDFI;
  ENTER_CRITICAL;
  reg=_peek(iw.pcodar)&0xE0;
  _poke(iw.pcodar,(BYTE)(reg|index|0x40));
  var=(_peek(iw.cdatap)&0xF0)|codec_freq[var].bits;
  _poke(iw.cdatap,var);
  _poke(iw.pcodar,reg|index);        /* write protect the registers */
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNTION : IwaveCodecStatus
//
// PROFILE: This function allows an application to retrive the contents
//          of any of the Codec's Status Registers CSR1R, CSR2I, and
//          CSR3I. As an illustration of the usage of this function the
//          following call returns the contents of CSR1R:
//
//          val = IwaveCodecStatus(CODEC_STATUS1).
//
//          For the other two registers, pass CODEC_STATUS2 and CODEC_
//          STATUS3 as arguments.
//
//########################################################################
BYTE IwaveCodecStatus(BYTE id)
{
 BYTE cstat=0x00;
 BYTE cidxr;

 ENTER_CRITICAL;

 switch(id)
 {
	case CODEC_STATUS1:
		  cstat= _peek(iw.pcodar+0x02);      /* read CSR1R */
		  break;
	case CODEC_STATUS2:
	case CODEC_STATUS3:
		  cidxr = _peek(iw.pcodar);          /* read CIDXR */
		  cidxr = (cidxr&0xE0)|id;
		  _poke(iw.pcodar,cidxr);            /* select CSRxI */
		  cstat= _peek(iw.cdatap);           /* read CSRxI */
		  break;
	default:
		  break;
 }
 LEAVE_CRITICAL;
 return(cstat);
}
//########################################################################
//
// FUNCTION: IwaveTimerStart
//
// PROFILE: This function sets off the codec timer. This is done by
//          setting CFIG2I[6] high.
//
//########################################################################
void IwaveTimerStart(void)
{
  ENTER_CRITICAL;
  _poke(iw.pcodar,(BYTE)((_peek(iw.pcodar)&0xE0)|_CFIG2I)); //select CFIG2I
  _poke(iw.cdatap,(BYTE)(_peek(iw.cdatap)|TIMER_ENABLE));   //set timer running
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveTimerStop
//
// PROFILE: This function turns off the codec timer. This is done by
//          setting CFIG2I[6] low.
//
//########################################################################
void IwaveTimerStop(void)
{
  ENTER_CRITICAL;
  _poke(iw.pcodar,(BYTE)((_peek(iw.pcodar)&0xE0)|_CFIG2I)); //select CFIG2I
  _poke(iw.cdatap,(BYTE)(_peek(iw.cdatap)&~TIMER_ENABLE));  //stop timer
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveSetTimer
//
// PROFILE: This function loads a value into the timer counter. Notice
//          that the lower byte of the counter is loaded last. This is
//          because writing to CLTIMI the general purpose counter is
//          loaded. The codec timer is a 10 us timer.
//
//          Note that reading these registers will not give the current
//          value of the counter but the value loaded into the registers
//          initially.
//
//########################################################################
void IwaveSetTimer(WORD cnt)
{
  BYTE reg;
//
  ENTER_CRITICAL;
  reg=_peek(iw.pcodar)&0xE0;
  _poke(iw.pcodar,reg|_CUTIMI);          // select CUTIMI
  _poke(iw.cdatap,(BYTE)(cnt>>8));       // write upper byte
  _poke(iw.pcodar,reg|_CLTIMI);          // select CLTIMI
  _poke(iw.cdatap,(BYTE)cnt);            // write lower byte
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveDataFormat
//
// PROFILE: This function allows the caller to set up CPDFI and CRDFI
//          registers to select sampling rate, data format, etc.
//
//          The first argument should reflect what the data format and
//          sample rate in CPDFI or CRDFI must be. The second argument
//          should be set to  _CPDFI (Playback data format) or _CRDFI
//          (Record). See the programmer's manual for details.
//
//          IwaveDataFormat(BIT8_ULAW|STEREO,_CRDFI) sets
//          the Record data Format to Stereo, 8-bit ulaw.
//
//########################################################################
void IwaveDataFormat(BYTE data,BYTE inx)
{ 
  BYTE reg;
//  
  reg=_peek(iw.pcodar)&0xE0;
  if (iw.cmode==CODEC_MODE1)  inx=_CPDFI;
  ENTER_CRITICAL;
  _poke(iw.pcodar,(BYTE)(CODEC_MCE|reg|inx));// turn CIDXR[MCE] on/ select register
  _poke(iw.cdatap,data);                     // set data format
  _poke(iw.pcodar,reg|inx);                  // turn CIDXR[MCE] off
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveCodecIrq
//
// PROFILE: This function disables or enables the Codec Interrupts. To
//          enable interrupts set CEXTI[2] high thus causing all interrupt
//          sources (CSR3I[6:4]) to pass onto the IRQ pin. To disable
//          interrupts set CEXTI[1]=0. To enable Code IRQs issue this call:
//
//          IwaveCodecIrq(CODEC_IRQ_ENABLE). To disable IRQs issue the call
//
//          IwaveCodeIrq(~CODEC_IRQ_ENABLE).
//
//########################################################################
void IwaveCodecIrq(BYTE mode)
{
  BYTE reg;

  ENTER_CRITICAL;
  reg=_peek(iw.pcodar)&0xE0;
  _poke(iw.pcodar,reg|_CSR3I);                  // select CSR3I
  _poke(iw.cdatap,0x00);					         // clear all interrupts
  _poke(iw.pcodar+0x02,0x00);                   // clear CSR1R
  _poke(iw.pcodar,reg|_CEXTI);                  // select CEXTI
  reg = _peek(iw.cdatap);
  if (mode==CODEC_IRQ_ENABLE)                   // enable Codec Irqs
		_poke(iw.cdatap,(BYTE)(reg|CODEC_IRQ_ENABLE));
  else                                          // disable Codec Irqs
		_poke(iw.cdatap,(BYTE)(reg&~CODEC_IRQ_ENABLE));
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveCodecTrigger
//
// PROFILE: This function allows an application to enable the codec record
//          or playback path or both paths. The following illustration
//          shows its usage:
//
//          IwaveCodecTrigger(RECORD) enables the record path and
//          IwaveCodecTrigger(RECORD|PLAYBACK) enables both
//          paths. The path enabling is done by setting CFIG1I[1:0]. Note
//          that these bits are not write-protected.
//
//
//########################################################################
void IwaveCodecTrigger(BYTE path)
{
  ENTER_CRITICAL;
  _poke(iw.pcodar,(BYTE)((_peek(iw.pcodar)&0xE0)|_CFIG1I)); // select CFIG1I
  _poke(iw.cdatap,(BYTE)(_peek(iw.cdatap)|path));           // enable path(s)
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwavePlayData
//
// PROFILE: This function sets up and triggers a DMA transfer of data
//          through the codec's playback. The caller can force the function
//          to block until the transfer is completed or to return
//          immediately.
//          The arguments to this function are:
//
//          size  - the size in bytes of the transfer
//          wait  - a TRUE or FALSE variable to indicate whether the
//                  function is to wait for the transfer to complete.
//          type  - set this to AUTO_READ if caller needs to have transfer
//                  reapeat over and over. Otherwise, set to DMA_READ.
//
//########################################################################
FLAG IwavePlayData(WORD size,BYTE wait,BYTE type)
{
	IwavePlayAccess(DMA_ACCESS);                 // select DMA cycles
	IwaveCodecCnt(PLAY,size);                    // set up play counter 
	iw.dma2->type=type;
	if (IwaveDmaCtrl(iw.dma2,size)!=DMA_OK)      // set up transfer 
		 return(DMA_BUSY);
	iw.dma2->flags|=(DMA_BUSY|CODEC_DMA);        // flag background
	iw.dma2->amnt_sent=0;
	iw.flags|=DMA_BUSY;                          // flag foreground 
	IwaveCodecTrigger(PLAYBACK);                 // Trigger DMA transfer
	if (wait)
	{
       IwaveDmaWait();			                  // Block til xfer is over
		 IwaveStopDma(PLAYBACK);
	}						                           // Reset flags and disable path
	return(DMA_OK);
}
//########################################################################
//
// FUNCTION: IwaveRecordData
//
// PROFILE: This function sets up and triggers a DMA transfer of data
//          through the codec's record path.
//
//          The arguments to this function are:
//
//          size  - the size in bytes of the transfer
//          wait  - a TRUE or FALSE variable to indicate whether the
//                  function is to wait for the transfer to complete.
//          type  - set this to AUTO_WRITE if caller needs to have transfer
//                  reapeat over and over. Otherwise, set to DMA_WRITE.
//
//########################################################################
FLAG IwaveRecordData(WORD size,BYTE wait,BYTE type)
{
	IwaveRecordAccess(DMA_ACCESS);              // select DMA cycles
	IwaveCodecCnt(REC,size);                    // program sample counters
	iw.dma1->type=type;
	if (IwaveDmaCtrl(iw.dma1,size)!=DMA_OK)     // set up transfer
		 return(DMA_BUSY);
	iw.dma1->flags|=(DMA_BUSY|CODEC_DMA);       // flag background
	iw.dma1->amnt_sent=0;
	iw.flags|=DMA_BUSY;                         // flag foreground
	IwaveCodecTrigger(RECORD);                  // Trigger DMA transfer
	if (wait)
	 {
		 IwaveDmaWait();		                    // Block til xfer is over
		 IwaveStopDma(RECORD); 	    				  // Reset flags and disable path
	 }
	return(DMA_OK);
}
//########################################################################
//
// FUNCTION: IwaveStopDma
//
// PROFILE: This function stops an active DMA transfer to or from the record
//          or playback FIFOs. Set the "path" variable to either PLAYBACK or
//          RECORD.
//########################################################################
void IwaveStopDma(BYTE path)
{
  DMA *dma;
  BYTE reg;

  if (path==PLAYBACK)
		dma=iw.dma2;
  else
		dma=iw.dma1;
  ENTER_CRITICAL;
  reg = _peek(iw.pcodar)&0xE0;
  _poke(iw.pcodar,reg|_CFIG1I);                    // select CFIG1I
  _poke(iw.cdatap,(BYTE)(_peek(iw.cdatap)&~path)); // disable playback path
  _poke(dma->single,dma->disable);                 // disable DMA channel
  dma->flags&=~(DMA_BUSY|CODEC_DMA);               // reset background flags
  iw.flags&=~DMA_BUSY;                             // reset foreground flag
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveCodecCnt
//
// PROFILE: This function loads the codec's sample counters with the
//          specified value. Notice that the upper byte of the counter
//          is loaded last and it is this action that causes the timer
//          to be loaded with all 16 bits.
//
//  args:
//			  index  - an index to CPDFI or CRDFI. These could be the symbolic
//                   constants _CPDFI or _CRDFI.
//         cnt    - total number of bytes comprising the samples.
//
//         As an illustration, to load the Playback Sample Counter issue
//         the call
//                     IwaveCodecCnt(PLAY,0x1624)
//
//########################################################################
void IwaveCodecCnt(BYTE index, WORD cnt)
{
 BYTE format,val,reg;

 reg=_peek(iw.pcodar)&0xE0;
 if (iw.cmode==CODEC_MODE1||index==PLAY)
	  _poke(iw.pcodar,reg|_CPDFI);
 else
	  _poke(iw.pcodar,reg|_CRDFI);
 format=_peek(iw.cdatap)&0xF0;
 val=format&0xE0;
 
 switch(val)
 {
  case 0x40:     /* 16 bit little endian */
  case 0xC0:     /* 16 bit big endian */
       cnt>>=1;
       break;
  case 0xA0:	  /* 16-bit ADPCM */
       cnt>>=2;
       break;
 }
 if((format&STEREO)&&(val!=0xA0))
    cnt>>=1;
 cnt--; 
 ENTER_CRITICAL;
 _poke(iw.pcodar,reg|index);
 _poke(iw.cdatap,(BYTE)cnt);         /* lower byte */
 _poke(iw.pcodar,reg|(--index));
 _poke(iw.cdatap,(BYTE)(cnt>>8));    /* upper byte */
 LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveCodecAccess
//
// PROFILE: This function allows the caller to enable or disable I/O access
//          to the Codec FIFOs. Set the argument to DMA_ACCESS or to
//          PIO_ACCESS. This function will automatically disable the play
//          and record paths (CFIG1I[1:0]=(0,0)). Also if you wish to
//          to select single channel DMA operation OR in the constant
//          DMA_SIMPLEX. Otherwise full duplex DMA operation is selected.
//
//########################################################################
void IwaveCodecAccess(BYTE type)
{
 BYTE reg;
//
 ENTER_CRITICAL;
 reg=_peek(iw.pcodar)&0xE0;
 _poke(iw.pcodar,reg|_CFIG1I|0x40);
 if (type==PIO_ACCESS)         // configure CFIG1I
	  _poke(iw.cdatap,(BYTE)(_peek(iw.cdatap)|PIO_ACCESS));
 else
	  _poke(iw.cdatap,(BYTE)((_peek(iw.cdatap)&~PIO_ACCESS)|type));
 _poke(iw.pcodar,reg|_CFIG1I); // write protect CFIG1I[7:2]
 LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwavePlayAccess
//
// PROFILE: This function has the same functionality as IwaveCodecAccess
//          but applies only to the Playback path.
//
//########################################################################
void IwavePlayAccess(BYTE type)
{
 BYTE reg;
//
 ENTER_CRITICAL;
 reg=_peek(iw.pcodar)&0xE0;
 _poke(iw.pcodar,reg|_CFIG1I|0x40);
 if (type==PIO_ACCESS)            // configure CFIG1I
	  _poke(iw.cdatap,(BYTE)(_peek(iw.cdatap)|0x40));
 else
	  _poke(iw.cdatap,(BYTE)((_peek(iw.cdatap)&0xBF)|type));
 _poke(iw.pcodar,reg|_CFIG1I);    // write protect CFIG1I[7:2]
 LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveRecordAccess
//
// PROFILE: This function has the same functionality as IwaveCodecAccess
//          but applies only to the Record path.
//
//########################################################################
void IwaveRecordAccess(BYTE type)
{
 BYTE reg;
//
 ENTER_CRITICAL;
 reg = _peek(iw.pcodar)&0xE0;
 _poke(iw.pcodar,reg|_CFIG1I|0x40);
 if (type==PIO_ACCESS)            // configure CFIG1I
	  _poke(iw.cdatap,(BYTE)(_peek(iw.cdatap)|0x80));
 else
	  _poke(iw.cdatap,(BYTE)((_peek(iw.cdatap)&0x7F)|type));
 _poke(iw.pcodar,reg|_CFIG1I);    // write protect CFIG1I[7:2]
 LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveEnableLineIn
//
// PROFILE: This function enables the stereo line-in inputs.
//
//########################################################################
void IwaveEnableLineIn(void)
{
  ENTER_CRITICAL;
  _poke(iw.p2xr,(BYTE)(_peek(iw.p2xr)&0xFE));     /* enable line-in */
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveDisableLineIn
//
// PROFILE: This function disables the stereo line-in inputs.
//
//########################################################################
void IwaveDisableLineIn(void)
{
  ENTER_CRITICAL;
  _poke(iw.p2xr,(BYTE)(_peek(iw.p2xr)|0x01));     /* disable line-in */
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveEnableMicIn
//
// PROFILE: This function enables both the mono and the stereo
//          Mic inputs to be disabled.
//
//########################################################################
void IwaveEnableMicIn(void)
{
  ENTER_CRITICAL;
  _poke(iw.p2xr,(BYTE)(_peek(iw.p2xr)|0x04));      /* Enable Mic-in */
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveDisableMicIn
//
// PROFILE: This function disables both the mono and the stereo
//          Mic inputs to be disabled.
//
//########################################################################
void IwaveDisableMicIn(void)
{
  ENTER_CRITICAL;
  _poke(iw.p2xr,(BYTE)(_peek(iw.p2xr)&0xFB));       /* disable Mic-in */
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveDisableOutput
//
// PROFILE: This function disables the stereo line-out outputs
//          (no sound).
//
//########################################################################
void IwaveDisableOutput(void)
{
  ENTER_CRITICAL;
  _poke(iw.p2xr,(BYTE)(_peek(iw.p2xr)|0x02));       /* disable output */
  LEAVE_CRITICAL;
}
//########################################################################
//
// FUNCTION: IwaveEnableOutput
//
// PROFILE: This function enables the stereo line-out outputs.
//
//########################################################################
void IwaveEnableOutput(void)
{
  ENTER_CRITICAL;
  _poke(iw.p2xr,(BYTE)(_peek(iw.p2xr)&0xFD));            /* enable output */
  LEAVE_CRITICAL;
}
