
//! @file vpbreg.h
//! @ingroup InternalAPI
//! @brief VPB hardware registry implementation
//!
//! Functions used to load configuration database from the @c PC into the
//! @c VPB @c DSP.  This database is known as the DSP Registry.  Each @c VPB
//! has its own registry.

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

    AUTHOR..: David Rowe
    DATE....: 3/10/97
    AUTHOR..: Ron Lee
    DATE....: 11/11/06


         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

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

#ifndef __VPBREG__
#define __VPBREG__

#include <vt/tonegen.h>

#include "dspfifo.h"
#include "utilfuncs.h"
#include "vpbapi.h"


//! @defgroup InternalAPI Internal API functions
//! @brief Internal API functions, documented for @c libvpb developers.
//!
//! These functions are not a part of the public api, they are not available
//! to users of @c libvpb.  They are used by the library internally and are
//! documented here for the benefit of people wishing to further develop the
//! library itself.

//! @defgroup InternalImpl Internal implementation detail
//! @brief Structures and functions local to a particular translation unit.
//!
//! These symbols are not a part of the public api, and are typically not even
//! available to other parts of the library other than where they are defined.
//! They are used by the library internally and are documented here for the
//! benefit of people wishing to further develop the library itself.


//! @defgroup VPBRegistry Hardware registry
//! @ingroup InternalAPI
//! @brief Structures to maintain a record of the available hardware and its
//!        configuration state.
//!@{
//{{{

// general defines 

#define	MAXCH		32    //!< max channels per VPB			

// channel status flags 

#define	RX		0x1   //!< channel receiving speech		
#define	TX		0x2   //!< channel transmitting speech		

// device driver types

//#define DD_ISA_PORT	0     //   ISA port I/O only device driver
//#define DD_ISA_RELAY	1     //   ISA relay FIFO device driver
#define DD_PCI		2     //!< PCI driver
//#define DD_V12PCI	3     //   V12PCI driver
//#define DD_V6PCI	3     //   V6PCI driver
#define DD_PRI		4     //!< OpenPri driver
#define DD_VTCORE	5     //!< VTCore card driver


class HostDSP;

//! Lookup table element for mapping vpb handles to a @a port on @a boardnum.
struct VPBHANDLE
{ //{{{
	//! Container type for the lookup table.
	typedef std::vector<VPBHANDLE>  List;

	int	board;      //!< The board number for this handle.
	int	channel;    //!< The port number for this handle.

	//! Convenience constructor.
	VPBHANDLE( int boardnum, int port )
	    : board( boardnum )
	    , channel( port )
	{}
}; //}}}


// make sure compiler doesnt mess with member alignment of this one
#pragma pack(1)

//! The DSP program "registry" info for each board 
struct VPBREG
{ //{{{

	//! Container type for all registered boards.
	typedef std::vector<VPBREG>  List;


    //! @name DSP data
    //! Data in this block is stored in the same format on the DSP
    //@{

	uint16_t	data;		//!< data reg for PC-DSP comms
	uint16_t	numch;		//!< number of channels
	uint16_t	chstat[MAXCH];	//!< status of each channel
	uint16_t	a_dnmess;	//!< addr of "down" message FIFO in DSP
	uint16_t	a_upmess;	//!< addr of "up" message FIFO in DSP
	uint16_t	szmess;		//!< size in words of message FIFOs
	uint16_t	a_rxdf[MAXCH];	//!< addresses of RX FIFOs in DSP	
	uint16_t	a_txdf[MAXCH];	//!< addresses of TX FIFOs in DSP
	uint16_t	szrxdf[MAXCH];	//!< size of RX FIFOs in DSP
	uint16_t	sztxdf[MAXCH];	//!< size of TX FIFOs in DSP
	uint16_t	lsf;		//!< length of superframe in words

    //@}

    //! @name PC specific info 
    //@{

	uint16_t	base;		//!< base address of VPB
	Fifo	       *dnmess;		//!< ptr to down message DSP FIFO in PC
	Fifo	       *upmess;		//!< ptr to down message DSP FIFO in PC
	Fifo	       *rxdf[MAXCH];	//!< ptrs to RX DSP FIFO info in PC
	Fifo	       *txdf[MAXCH];	//!< ptrs to TX DSP FIFO info in PC
	VPB_MODEL	model;		//!< VPB model
	uint16_t	ddmodel;	//!< VPB Device Driver model

	float		defRecordGain;	//!< default record (Tx) gain
	float		defPlayGain;	//!< default play (Rx) gain
	float		defSRecordGain;	//!< default record (Tx) gain for station
	float		defSPlayGain;	//!< default play (Rx) gain for station

	uint16_t	defbal1;	//!< default codec balance register 1
	uint16_t	defbal2;	//!< default codec balance register 2
	uint16_t	defbal3;	//!< default codec balance register 3
	uint16_t	defSbal1;	//!< default codec balance register 1 for station
	uint16_t	defSbal2;	//!< default codec balance register 2 for station
	uint16_t	defSbal3;	//!< default codec balance register 3 for station

	char		mdate[12];	//!< Manufacture Date
	char		revision[8];	//!< Revision number
	char		serial_n[10];	//!< Serial Number

	float	defRecordGainDown;	//!< record gain down control for better DTMF

	std::vector<int> handles;       //!< lookup table of the handles for each port.
	int	         cardnum;	//!< The number of the card as opened by the driver
	int	         cardtypnum;	//!< The number of the card of this type
	Country::List    country;	//!< Pointers to country specific data for each port
	ToneGen::List    toneg;         //!< Pointers to @c ToneGen instances for each port

	struct {
		int chan;               //!< listening port number
		int board;              //!< listening board number
	} listen_info[MAXCH];		//!< Used to keep a track of the listens

	struct TD     **toned;		//!< Pointer to Tone detector state variables
	void	       *chans;		//!< Pointer to Channel state variables
	HostDSP        *hostdsp;	//!< Pointer to the Host DSP object
	void	       *cardinfo;	//!< Pointer to Conf Info section for this card

	bool	        useconf;	//!< Flag @c true if a config file was read.

    //@}

}; //}}}

#pragma pack()	// back to default alignment

//XXX This one is rather badly named now, since the V4PCI DSP implementation
//    derives from it too.  We can fix that in the next major iteration though.
//! Base class for host processor based card types.
class HostDSP
{ //{{{
protected:

	//! Reference to the @c VPBREG structure for this @c %HostDSP.
	VPBREG	   &m_reg;

	//! Bare bones constructor for hardware DSP implementations.
	HostDSP( bool, VPBREG &reg ) : m_reg( reg ) { reg.hostdsp = this; }


public:

	//! Constructor
	HostDSP( VPBREG &reg );

	//! Destructor
	virtual ~HostDSP() {}


    //! @name Port reinitialisation
    //@{ //{{{

	//! Reset @a port to its default cold-start state.
	virtual void Reset( unsigned int port ) = 0;

    //@} //}}}

    //! @name Port localisation
    //@{ //{{{

	//! Configure the hardware for @a country on @a port of this board.
	virtual void SetCountry( int port, const Country *country ) = 0;

	//XXX These methods do not belong in the base class.  FIXME
	//! Override the default impedance for ProSLIC ports.
	virtual void SetPSImpedance( int port, int impedance )
	{ //{{{
		(void)port;
		(void)impedance;
	} //}}}

	//! Override the default impedance for VDAA ports.
	virtual void SetVDAAImpedance( int port, int impedance )
	{ //{{{
		(void)port;
		(void)impedance;
	} //}}}

        //! Configure the hook-flash detection window
        virtual void SetFlashTime( int port, uint16_t min, uint16_t max)
	{ //{{{
		(void)port;
		(void)min;
		(void)max;
	} //}}}

    //@} //}}}

    //! @name Port state
    //@{ //{{{

	//! Set the hook state of @a port.
	virtual void SetHookState( int port, HookState hookstate ) = 0;

	//! Pad a partial transmit frame for forwarding to the hardware.
	virtual void PadTxFrame( int port ) = 0;

	//! Block until the transmit buffers for @a port are empty.
	virtual void WaitForTxEmpty( int port ) = 0;

    //@} //}}}

    //! @name Port Audio control
    //@{ //{{{

	virtual float GetHWPlayGain( unsigned int port )
	{ //{{{
		(void)port;
		return 0.0;
	} //}}}

	virtual float GetHWRecordGain( unsigned int port )
	{ //{{{
		(void)port;
		return 0.0;
	} //}}}

    //@} //}}}


    //! @name Port bridging and monitoring
    //@{ //{{{

	//! Create a full duplex tap to @a port of the audio from @a srcport on @a srcboard.
	virtual void TapListen( unsigned int port,
				unsigned int srcboard,
				unsigned int srcport )
	{ //{{{
		(void)srcboard;
		(void)srcport;
		throw VpbException("[%d/%d] TapListen not implemented for this hardware",
				   m_reg.cardnum, port);
	} //}}}

	//! Remove a half duplex bridge or full duplex tap from @a port.
	virtual void UNListen( unsigned int port )
	{ //{{{
		throw VpbException("[%d/%d] UNListen not implemented for this hardware",
				   m_reg.cardnum, port);
	} //}}}

    //@} //}}}

}; //}}}


class VPBRegister
{ //{{{
    private:

	CONF_INFO	m_conf;
	llc_list       *m_confdata;

	VPBHANDLE::List	m_handles;
	VPBREG::List	m_reg;


    public:

	VPBRegister();
	~VPBRegister();

	//! Return the number of boards registered.
	unsigned int GetBoardCount() const  { return m_conf.cardcount; }

	//! @brief Return the global country code from <tt>vpb.conf</tt>.
	//!
	//! If no global country code was configured there, it will return 0.
	unsigned int GetCountryCode() const { return m_conf.country_code; }

	VPBREG &GetReg( int board )	    { return m_reg[board]; }

	//! Look up the @c VPBHANDLE entry for @a handle.
	const VPBHANDLE &LookupHandle( int handle ) const
	{ //{{{
		return m_handles[handle];
	} //}}}

	//! Return a new handle for a @a port on some @a board.
	int NewHandle( int board, int port )
	{ //{{{
		m_handles.push_back( VPBHANDLE(board, port) );
		return m_handles.size() - 1;
	} //}}}

}; //}}}


//!@} //}}}  group VPBRegistry

#endif	/* #ifndef __VPBREG__	*/

