/*---------------------------------------------------------------------------*\

	FILE....: CONFIG.CPP
	TYPE....: C Program
	AUTHOR..: David Rowe
	DATE....: 28/11/97

	Helper functions for talking to the VPB config manager.

    16/5/98		Horse		Added PACKED_FIFO_UP support
    20/5/98		Horse		Added FIFO_UP_24K support


         Voicetronix Voice Processing Board (VPB) Software
         Copyright (C) 1999-2007 Voicetronix www.voicetronix.com.au

         This library is free software; you can redistribute it and/or
         modify it under the terms of the GNU Lesser General Public
         License as published by the Free Software Foundation; either
         version 2.1 of the License, or (at your option) any later version.

         This library is distributed in the hope that it will be useful,
         but WITHOUT ANY WARRANTY; without even the implied warranty of
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
         Lesser General Public License for more details.

         You should have received a copy of the GNU Lesser General Public
         License along with this library; if not, write to the Free Software
         Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
         MA  02110-1301  USA

\*---------------------------------------------------------------------------*/

#include <assert.h>
#include <stdlib.h>
#include "config.h"
#include "messages.h"
#include "mess.h"


/*--------------------------------------------------------------------------*\

	FUNCTION.: config_create_object
	AUTHOR...: David Rowe
	DATE.....: 25/11/97

	Sends a message to the config manager to create a new object.

\*--------------------------------------------------------------------------*/

void config_create_object(Comm *c, USHORT board, USHORT cls, USHORT id, USHORT ch, USHORT data)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT cls		Class of object to create	
//  USHORT id		Unique object identifier
//  USHORT ch		(Optional) channel object is associated with
//  USHORT data		(Optional) data
{
	word   mobj[PC_LCONFIG_OBJ];

	assert(c != NULL);
	assert(board < MAX_VPB);

	mobj[0] = PC_LCONFIG_OBJ;
	mobj[1] = PC_CONFIG_OBJ;
	mobj[2] = cls;			// class		
	mobj[3] = id;			// object ID		
	mobj[4] = ch;			// channel		
	mobj[5] = data;			// size of FIFO		

	c->PutMessageVPB(board, mobj);

	// if we are creating a DSPFIFO, perform PC side of init here

	if( cls == FIFO_UP || cls == FIFO_DOWN || cls==PACKED_FIFO_UP
	 || cls==FIFO_UP_24K || cls==FIFO_DOWN_24K || cls==PACKED_FIFO_DOWN )
	{
		word   maf[DSP_LCONFIG_AF];
		USHORT mid,mch,maddr;
		VPBREG *v = c->vpbreg(board);

		assert(data != 0);

		// wait for DSP to send us the FIFO address in DSP

//		mprintf("Getting FIFO address from DSP...\n");
		c->WaitForMessageVPB(board, maf, DSP_CONFIG_AF, 1);
		mid = maf[2];
		mch = maf[3];
		maddr = maf[4];

		assert(id == mid);
		assert(mch == ch);

		// init DSP FIFO object in PC
//		mprintf(" init DSP FIFO object in PC\n");

		if(cls == FIFO_UP || cls==PACKED_FIFO_UP || cls==FIFO_UP_24K) {
			v->a_rxdf[mch] = maddr;
			v->rxdf[ch] = new V4PCIDspFifo(V4PCI_DSP::GetHip(),
						       v->cardtypnum, maddr);
		} else {
			v->a_txdf[mch] = maddr;
			v->txdf[ch] = new V4PCIDspFifo(V4PCI_DSP::GetHip(),
						       v->cardtypnum, maddr);
		}
	}
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_create_wire
	AUTHOR...: David Rowe
	DATE.....: 25/11/97

	Sends a message to the config manager to create a wire joining two
	objects.

\*--------------------------------------------------------------------------*/

void config_create_wire(Comm *c, USHORT board, USHORT src, USHORT dest)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT src		Source object identifier	
//  USHORT dest		Destination object identifier	
{
	word   mwire[PC_LCONFIG_WIRE];

	assert(c != NULL);
	assert(board < MAX_VPB);

	mwire[0] = PC_LCONFIG_WIRE;
	mwire[1] = PC_CONFIG_WIRE;
	mwire[2] = src;			// source object ID	
	mwire[3] = dest;		// dest object ID	

	c->PutMessageVPB(board, mwire);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_clear
	AUTHOR...: David Rowe
	DATE.....: 28/11/97

	Sends a message to the config manager to clear the current 
	configuration.

\*--------------------------------------------------------------------------*/

void config_clear(Comm *c, USHORT board)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
{
	word   mclear[PC_LCONFIG_CLR];

	assert(c != NULL);
	assert(board < MAX_VPB);

	mclear[0] = PC_LCONFIG_CLR;
	mclear[1] = PC_CONFIG_CLR;

	c->PutMessageVPB(board, mclear);

	// delete any DSP fifos if they exist

	VPBREG *v = c->vpbreg(board);

	for(int i=0; i < MAXCH; ++i) {
		if (v->txdf[i] != NULL) {
			delete v->txdf[i];
			v->txdf[i] = NULL;
		}
		if (v->rxdf[i] != NULL) {
			delete v->rxdf[i];
			v->rxdf[i] = NULL;
		}
	}
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_run
	AUTHOR...: David Rowe
	DATE.....: 28/11/97

	Sends a message to the config manager to enable execution of the
	current signal processing configuration.

\*--------------------------------------------------------------------------*/

void config_run(Comm *c, USHORT board)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
{
	word   mrun[PC_LCONFIG_RUN];

	assert(c != NULL);
	assert(board < MAX_VPB);

	mrun[0] = PC_LCONFIG_RUN;
	mrun[1] = PC_CONFIG_RUN;

	c->PutMessageVPB(board, mrun);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_stop
	AUTHOR...: David Rowe
	DATE.....: 28/11/97

	Sends a message to the config manager to disable execution of the
	current signal processing configuration.

\*--------------------------------------------------------------------------*/

void config_stop(Comm *c, USHORT board)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
{
	word   mstop[PC_LCONFIG_STOP];

	assert(c != NULL);
	assert(board < MAX_VPB);

	mstop[0] = PC_LCONFIG_STOP;
	mstop[1] = PC_CONFIG_STOP;

	c->PutMessageVPB(board, mstop);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_clear_wire
	AUTHOR...: David Rowe
	DATE.....: 9/2/98

	Sends a message to the config manager to clear all input wires to
	a specified object.  This function must be called before re-wiring 
	an object.

\*--------------------------------------------------------------------------*/

void config_clear_wire(Comm *c, USHORT board, USHORT obj)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT obj		object identifier	
{
	word   mwire[PC_LCONFIG_NWIRE];

	assert(c != NULL);
	assert(board < MAX_VPB);

	mwire[0] = PC_LCONFIG_NWIRE;
	mwire[1] = PC_CONFIG_NWIRE;
	mwire[2] = obj;				// object ID	

	c->PutMessageVPB(board, mwire);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_enable_object
	AUTHOR...: David Rowe
	DATE.....: 9/2/98

	Sends a message to the config manager to enable an object.

\*--------------------------------------------------------------------------*/

void config_enable_object(Comm *c, USHORT board, USHORT obj)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT obj		object identifier	
{
	word   mwire[PC_LCONFIG_EN];

	assert(c != NULL);
	assert(board < MAX_VPB);

	mwire[0] = PC_LCONFIG_EN;
	mwire[1] = PC_CONFIG_EN;
	mwire[2] = obj;				// object ID	

	c->PutMessageVPB(board, mwire);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_enable_two_objects
	AUTHOR...: David Rowe
	DATE.....: 22/9/98

	Sends a message to the config manager to enable two objects at the
	same time.  This is useful when two objects MUST be switched on at
	the same time, eg for ADPCM sampling where loosing a buffer will
	mean memory problems.

\*--------------------------------------------------------------------------*/

void config_enable_two_objects(Comm *c, USHORT board, USHORT obj1, USHORT obj2)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT obj		object identifier	
{
	word   mwire[PC_LCONFIG_EN2];

	assert(c != NULL);
	assert(board < MAX_VPB);

	mwire[0] = PC_LCONFIG_EN2;
	mwire[1] = PC_CONFIG_EN2;
	mwire[2] = obj1;			// object ID	
	mwire[3] = obj2;			// object ID	

	c->PutMessageVPB(board, mwire);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_enable_object_list
	AUTHOR...: David Rowe
	DATE.....: 16/10/98

	Sends a message to the config manager to enable a list of objects
	at the same time.  This may be necessary, eg in the case of ADPCM
	play back where all objects must start at the same time to prevent
	memory problems.

\*--------------------------------------------------------------------------*/

void config_enable_object_list(Comm *c, USHORT board, USHORT objlist[], int nobj)
//  Comm   *c;			comm object holds config init
//  USHORT board		VPB board number
//  USHORT objlist[]	list of object identifier	
//  int	   nobj			number of objects in list	
{
	word    m[2+CONFIG_MAX_LIST];

	assert(c != NULL);
	assert(board < MAX_VPB);
	assert(nobj <= CONFIG_MAX_LIST);

	m[0] = 2 + nobj;
	m[1] = PC_CONFIG_ENLIST;

	for(int i=0; i < nobj; ++i)
		m[2+i] = objlist[i];

	c->PutMessageVPB(board, m);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_disable_object
	AUTHOR...: David Rowe
	DATE.....: 9/2/98

	Sends a message to the config manager to disable an object.

\*--------------------------------------------------------------------------*/

void config_disable_object(Comm *c, USHORT board, USHORT obj)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT obj		object identifier	
{
	word   mwire[PC_LCONFIG_DIS];

	assert(c != NULL);
	assert(board < MAX_VPB);

	mwire[0] = PC_LCONFIG_DIS;
	mwire[1] = PC_CONFIG_DIS;
	mwire[2] = obj;				// object ID	

	c->PutMessageVPB(board, mwire);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_rate8k
	AUTHOR...: David Rowe
	DATE.....: 8/6/98

	Sends a message to the config manager to configure an object for 8 kHz
	sampling rate operation.

\*--------------------------------------------------------------------------*/

void config_rate8k(Comm *c, USHORT board, USHORT obj)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT obj		object identifier	
{
	word   mwire[PC_LCONFIG_8K];

	assert(c != NULL);
	assert(board < MAX_VPB);

	mwire[0] = PC_LCONFIG_8K;
	mwire[1] = PC_CONFIG_8K;
	mwire[2] = obj;				// object ID	

	c->PutMessageVPB(board, mwire);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_rate6k
	AUTHOR...: David Rowe
	DATE.....: 8/6/98

	Sends a message to the config manager to configure an object for 6 kHz
	sampling rate operation.

\*--------------------------------------------------------------------------*/

void config_rate6k(Comm *c, USHORT board, USHORT obj)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT obj		object identifier	
{
	word   mwire[PC_LCONFIG_6K];

	assert(c != NULL);
	assert(board < MAX_VPB);

	mwire[0] = PC_LCONFIG_6K;
	mwire[1] = PC_CONFIG_6K;
	mwire[2] = obj;				// object ID	

	c->PutMessageVPB(board, mwire);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_packrate
	AUTHOR...: David Rowe
	DATE.....: 25/6/98

	Sends a message to the config manager to configure the packing 
	rate of a PACK or PACK_FIFO_UP object.

\*--------------------------------------------------------------------------*/

void config_packrate(Comm *c, USHORT board, USHORT obj, USHORT packrate)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT obj		object identifier	
//	USHORT packrate	packing rate (1,2, or 4)
{
	word   mwire[PC_LCONFIG_PACK];

	assert(c != NULL);
	assert(board < MAX_VPB);
	assert((packrate ==1) || (packrate == 2) || (packrate == 4));

	mwire[0] = PC_LCONFIG_PACK;
	mwire[1] = PC_CONFIG_PACK;
	mwire[2] = obj;				// object ID	
	mwire[3] = packrate;

	c->PutMessageVPB(board, mwire);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_apdcm_reset
	AUTHOR...: David Rowe
	DATE.....: 26/6/98

	Sends a message to the config manager to reset the state variables
	of an ADPCM encoder or decoder object.  This should occur at the
	start of each record or play.

\*--------------------------------------------------------------------------*/

void config_adpcm_reset(Comm *c, USHORT board, USHORT obj)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT obj		object identifier	
{
	word   m[PC_LCOMP_ADPCMRES];

	assert(c != NULL);
	assert(board < MAX_VPB);

	m[0] = PC_LCOMP_ADPCMRES;
	m[1] = PC_COMP_ADPCMRES;
	m[2] = obj;				// object ID	

	c->PutMessageVPB(board, m);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_connect_to_zerobuf
	AUTHOR...: David Rowe
	DATE.....: 8/9/98

	Sends a message to the config manager to connect an object to the
	zero buffer, effectively feeding that object with zeros.

\*--------------------------------------------------------------------------*/

void config_connect_to_zerobuf(Comm *c, USHORT board, USHORT obj)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT obj		object identifier	
{
	word   m[PC_LCONFIG_ZEROBUF];

	assert(c != NULL);
	assert(board < MAX_VPB);

	m[0] = PC_LCONFIG_ZEROBUF;
	m[1] = PC_CONFIG_ZEROBUF;
	m[2] = obj;				// object ID	

	c->PutMessageVPB(board, m);
}

/*--------------------------------------------------------------------------*\

	FUNCTION.: config_flush_fifo
	AUTHOR...: David Rowe
	DATE.....: 8/9/98

	Sends a message to the config manager to empty a fifo completely,
	used when configuring for play to ensure no scata is present.

\*--------------------------------------------------------------------------*/

void config_flush_fifo(Comm *c, USHORT board, USHORT obj)
//  Comm   *c;		comm object holds config init
//  USHORT board	VPB board number
//  USHORT obj		object identifier	
{
	word   m[PC_LCONFIG_FLUSHFIFO];

	assert(c != NULL);
	assert(board < MAX_VPB);

	m[0] = PC_LCONFIG_FLUSHFIFO;
	m[1] = PC_CONFIG_FLUSHFIFO;
	m[2] = obj;				// object ID	

	c->PutMessageVPB(board, m);
}

