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

    FILE....: COMM.H
    TYPE....: C Function Header File
    AUTHOR..: David Rowe
    DATE....: 2/10/97
    AUTHOR..: Ron Lee
    DATE....: 11/11/06

    Functions used for PC to DSP communications, which includes passing
    messages to and from the DSP, and transfering information to and from
    FIFOs in the DSP.


         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 __COMM__
#define __COMM__

#include "vpbreg.h"
#include "messages.h"


// return codes for message functions below 

#define	COMM_MAX_MESSDSPPC	512	// maximum message length from DSP to PC
#define	COMM_MAX_MESSPCDSP	128	// maximum message length from PC to DSP
#define	COMM_EMPTY		2	// read failed as no messages		  

#define V4PCI_LSF		160	// Length in samples of V4PCI superframe

class Comm;

//XXX does this really belong in this file?
//! DSP interface implementation for OpenLine cards.
class V4PCI_DSP : public HostDSP
{ //{{{
private:

    static Hip *ms_hip;

    uint32_t	m_addr_assert;	    //!< address of assert flag in DSP
    uint32_t	m_addr_reg;	    //!< address of registry info in DSP
    uint16_t	m_len_reg;	    //!< length of registry info in DSP


    //! Obtains a text string from the DSP.
    //{{{
    //! The global name passed to this function is assumed to point to the
    //! string required.
    //!
    //! @param board VPB board number
    //! @param s     string uploaded from DSP
    //! @param name  name of ptr to string in DSP program
    //}}}
    void GetStringFromDSP(unsigned short board, char *s, const char *name);


public:

    static Hip *GetHip() { return ms_hip; }


    V4PCI_DSP(Comm *comm, VPBREG &reg);

    ~V4PCI_DSP() {}


    void Reset( unsigned int /*port*/ ) {}
    void SetCountry( int, const Country* ) {}

    void SetHookState( int port, HookState hookstate );

    void PadTxFrame( int port );
    void WaitForTxEmpty( int port );

    void UNListen( unsigned int port );

    //! Debug function that checks the DSP to see if an assert occurred,
    //! which hangs the DSP.  If an assert occurs this method throws a Wobbly.
    void CheckForAssert(unsigned short board);

    void IicRead(unsigned short addr, unsigned short length, uint16_t *buf)
    { //{{{
	ms_hip->ReadIic(m_reg.cardtypnum, addr, length, buf);
    } //}}}

    void IicWrite(unsigned short addr, unsigned short length, uint16_t *buf)
    { //{{{
	ms_hip->WriteIic(m_reg.cardtypnum, addr, length, buf);
    } //}}}

}; //}}}


class Comm
{ //{{{
    private:

	VPBRegister         m_reg;


    public:

	//! Constructor.  The @c InitBoards() method actually opens the comm links.
	Comm() {}

	//! Closes down the comm link to the VPBs.
	~Comm();

	//! Second stage initialisation.
	//{{{
	//! This permits the board specific code to access the global @c %Comm
	//! object and the @c VPBRegister during their initialisation.
	//}}}
	void InitBoards();

	//! Return the total number of VPB boards currently registered.
	unsigned int GetBoardCount() const { return m_reg.GetBoardCount(); }

	//! @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_reg.GetCountryCode(); }

	//! Send a message to the DSP message queue.
	//{{{
	//! @param board The VPB board number.
	//! @param mess  A pointer to the message to send.  Its length is in
	//!              the first word.
	//}}}
	void PutMessageVPB(unsigned short board, uint16_t *mess);

	//! Gets a message from the DSP message queue.
	//{{{
	//! The length of the message is stored in its first word.
	//!
	//! @param board The VPB board number.
	//! @param mess  A pointer to storage for the message.
	//!
	//! @return @c VPB_OK if a message was read, else @c COMM_EMPTY if no
	//!         messages were in the queue.
	//!
	//! @warning @b NEVER call this function.  It is only safe to be
	//!          called from a single thread at a time and the
	//!          @c MonitorMessageQueue thread already has that privilege.
	//}}}
	int GetMessageVPB(unsigned short board, uint16_t *mess);

	//! Wait for a DSP message of a certain type.
	//{{{
	//! Messages of other types are discarded.
	//!
	//! @param board The VPB board number.
	//! @param mess  A pointer to storage for the message.  It must be
	//!              sufficient to store the desired message.
	//! @param mtype The type of message to wait for.
	//! @param wait  The number of seconds to wait for it.
	//!
	//! @exception Wobbly will be thrown if the @a wait time elapses and
	//!                   the message has not been received.
	//}}}
	void WaitForMessageVPB(unsigned short board, uint16_t *mess,
			       unsigned short mtype, unsigned short wait);

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

	//! Return a new handle for a @a port on some @a board.
	int NewHandle( int board, int port )
	{ //{{{
		return m_reg.NewHandle( board, port );
	} //}}}

	//! Return a pointer to the @c VPBREG structure for some @a board.
	VPBREG *vpbreg(unsigned short board);

}; //}}}

#endif	/* #ifndef __COMM__	*/

