/*
 *  plotndmn.C from ObjectProDSP 0.1
 *  Copyright (C) 1994, Mountain Math Software. All rights reserved.
 *  
 *  This file is part of ObjectProDSP, a tool for Digital Signal
 *  Processing design, development and implementation. It is free
 *  software provided you use and distribute it under the terms of
 *  version 2 of the GNU General Public License as published
 *  by the Free Software Foundation. You may NOT distribute it or
 *  works derived from it or code that it generates under ANY
 *  OTHER terms.  In particular NONE of the ObjectProDSP system is
 *  licensed for use under the GNU General Public LIBRARY License.
 *  Mountain Math Software plans to offer a commercial version of
 *  ObjectProDSP for a fee. That version will allow redistribution
 *  of generated code under standard commercial terms.
 *  
 *  This program 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 General Public License for more details.
 *  
 *  You should have received a copy of version 2 of the GNU General
 *  Public License along with this program. See file COPYING. If not
 *  or if you wish information on commercial versions and licensing
 *  write Mountain Math Software, P. O. Box 2124, Saratoga, CA 95070,
 *  USA, or send us e-mail at: support@mtnmath.com.
 *  
 *  You may also obtain the GNU General Public License by writing the
 *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 *  USA.  However if you received a copy of this program without the
 *  file COPYING or without a copyright notice attached to all text
 *  files, libraries and executables please inform Mountain Math Software.
 *  
 *  ObjectProDSP is a trademark of Mountain Math Software.
 */
#include <iostream.h>

#include "ObjProArith/hrdcmp.h"
#include "ObjProShare/shared.h"
#include "ObjProArith/hrdarth.h"

#include "ObjProGui/sigintfc.h"
#include "ObjProGui/intfc.h"
#include "ObjProGui/user.h"
#include "ObjProGui/remcom.h"
#include "ObjProGui/dspcom.h"
#include "ObjProGen/newaloc.h"
#include "ObjProDSPint/netlnk.h"

#include "ObjProGui/plotdatd.h"

#include "ObjProComGui/cgidbg.h"
#include "ObjProGui/yacintfc.h"
#include "ObjProUsr/plotnd.h"


void PlotNode::NewSampleRate()
{
 	// LogOut << "PlotNode::NewSampleRate called for `" << GetName() << "'\n" ;
	if (SetupState != RemoteSetupDone) return ;
	const Length = sizeof(int) + sizeof(double);
	char Buf[Length];
	for (int i = 0 ; i < GetIn(); i ++) {
		MoveNBytes(Buf,(char *) &i, sizeof(int)) ;
		MoveNBytes(Buf + sizeof(int), (char *)
			&(GetInLink(i)->GetTiming()->SampleRate),
			sizeof(double));
		PacketHeader Head = PlotPacketHeader(PacketWindowPlotControl,
			GetPlotId(),PlotControlNewSampleRate,Length);
		WriteSeg->WritePacket(Head,Buf);
/*
 *		LogOut << "Sent new sample rate " << GetInLink(i)->GetTiming()
 *			->SampleRate << " for node `" << GetName() << "'.\n"  ;
 */
	}
}

void PlotNode::RemoteSetup(RemoteSetupState Goal)
{
	AllocateBuffers();
/*
 *	LogOut << "PlotNode::RemoteSetup: Goal = " << Goal << 
 *		", State = " << SetupState << "\n" ;
 */ 
	if (SetupState >= Goal) return ;
	switch (SetupState) {
case RemoteSetupClear:
		ThePlotController.GetPlotId(this) ;
		SetupState = RemoteSetupIdReq;
		if (SetupState >= Goal) return ;
case RemoteSetupIdReq:
		// LogOut << "PlotNode::RemoteSetup - Checking for PlotId\n";
		while (!PlotId) CheckReadAndSleep() ;
		 // LogOut << "Got plot Id = " <<  PlotId << "\n" ;
		SetupState = RemoteSetupIdRec ;
		if (SetupState >= Goal) return ;
case RemoteSetupIdRec:
		// LogOut << "Sending header\n";
		SendHeader() ;
		SetupState = RemoteSetupSendResample ;
		// LogOut << "Header sent\n";
		if (SetupState >= Goal) return ;
case RemoteSetupSendResample:
		
		while (!HeaderComplete) {
			CheckReadAndSleep() ;
			// LogOut << "Header not complete.\n" ;
		}
		SetupState = RemoteSetupDone ;
case RemoteSetupDone:
		return ;
	}
}


// void TestAlloc(const char * Msg);

void PlotNode::AllocateBuffers()
{
	if (State.IsX()) {
		if (X_DataBufPtrs) return ;
    	NextWordInBuf = new int [Channels] ;
		X_DataBufPtrs = new MachWord * [Channels] ;
    	for (int i = 0 ; i < Channels ; i++) {
        	X_DataBufPtrs[i] = (MachWord *)
				new MachWordCast [MaxPacketSize/sizeof(MachWord)];
        	NextWordInBuf[i] = 0;
    	}
		return;
	}
	if (DataBufPtrs) return ;
	// LogOut << "Allocating " <<Channels << "\n" ;
	DataBufPtrs = new int16 * [Channels] ;
	NextWordInBuf = new int [Channels] ;
    for (int i = 0 ; i < Channels ; i++) {
        DataBufPtrs[i] = new int16 [MaxPacketSize>>1];
        NextWordInBuf[i] = 0;
    }
	// LogOut << "Allocating done\n" ;

}

void PlotNode::CheckRemoteSetup()
{
	// LogOut << "PlotNode::CheckRemoteSetup\n" ;
	RemoteSetup() ;
}


void PlotNode::SendHeader()
{
	DbgError("PlotNode::SendHeader", "base function called");
}

void PlotNode::X_CheckBuffer(int Channel)
{
	if (NextWordInBuf[Channel] >= ((MaxPacketSize-sizeof(MachWord)) /
			sizeof(MachWord)) -1) X_WriteBuffer(Channel);

}

void PlotNode::X_WriteBuffer(int Channel)
{
/*
 *	LogOut << "PlotNode::X_WriteBuffer(" << Channel << ") plotid = "
 *		<< GetPlotId() <<  ", NextWord = " << NextWordInBuf[Channel] << "\n" ;
 */
	if (!NextWordInBuf[Channel]) return ;
	PacketHeader Head = PlotPacketHeader(PacketWindowPlotData,
		GetPlotId(),Channel,NextWordInBuf[Channel]* sizeof(MachWord));
	WriteSeg->WritePacket(Head,(char *) X_DataBufPtrs[Channel]);
/*
 *	LogOut << "PlotNode::Wrote buffer of " <<
 *		(NextWordInBuf[Channel] << 1) << " bytes.\n" ;
 */
/*
 *	LogOut << "NextWordInBuf = " << (void *) NextWordInBuf <<
 *		", Channel = " << Channel << "\n" ;
 */
	NextWordInBuf[Channel] = 0;
}
void PlotNode::CheckBuffer(int Channel)
{
	if (NextWordInBuf[Channel] >= ((MaxPacketSize-2) >> 1) -1)
		WriteBuffer(Channel);

}

void PlotNode::WriteBuffer(int Channel)
{
/*
 *	LogOut << "PlotNode::WriteBuffer(" << Channel << ") plotid = "
 *		<< GetPlotId() << "\n" ;
 */	
	if (State.IsX()) {
		X_WriteBuffer(Channel);
		return ;
	}
	if (!NextWordInBuf[Channel]) return ;
	PacketHeader Head = PlotPacketHeader(PacketWindowPlotData,
		GetPlotId(),Channel,NextWordInBuf[Channel]<<1);
	WriteSeg->WritePacket(Head,(char *) DataBufPtrs[Channel]);
/*
 *	LogOut << "PlotNode::Wrote buffer of " <<
 *		(NextWordInBuf[Channel] << 1) << " bytes.\n" ;
 */
/*
 *	LogOut << "NextWordInBuf = " << (void *) NextWordInBuf <<
 *		", Channel = " << Channel << "\n" ;
 */
	NextWordInBuf[Channel] = 0;
}

void PlotNode::WriteDataWord(CxMachWord Word,int Channel)
{
	DataPlotHeader& TheDataPlot = *(GetDataPlot());
	MachWord RealWord = MachReal(Word);
	MachWord ImagWord = MachImag(Word);
	if (!State.IsX())
		if (TheDataPlot.GetStreamType() == PlotPairs) {
		double Temp ;
/*
 *		LogOut << "Scaling (" << RealWord << ", " << ImagWord
 *			<< ")\n" ;
 */
		RealWord=TheDataPlot.GetScaleX().DoScale(RealWord,Temp);
		ImagWord=TheDataPlot.GetScaleY(Channel).DoScale(ImagWord,Temp);
/*
 *		LogOut << "Scaled to (" << RealWord << ", " << ImagWord
 *			<< ")\n" ;
 */
	}
	WriteDataWord(RealWord,Channel);
	WriteDataWord(ImagWord,Channel);
}


void PlotNode::WriteDataWord(MachWord Word,int Channel)
{
/*
 *	LogForm("PlotNode::WriteDataWord Word = %d, GetDataPlot = 0x%x",
 *		(long) Word, (long) GetDataPlot());
 *	LogForm("Channel = 0x%x", (long) GetDataPlot()->GetChannel(0));
 */

	if (State.IsX()) {
		X_CheckBuffer(Channel);
		X_DataBufPtrs[Channel][NextWordInBuf[Channel]++] = Word ;
/*
 *		TheLog << "PlotNode::WriteDataWord " << Word << ", 0x" << hex << (long)
 *			Word << dec << "\n" ;
 */
		X_CheckBuffer(Channel);
		return;
	}
#ifndef linux
	DataPlotHeader& TheDataPlot = *(GetDataPlot());
	if (!PrescaleFlag)
	    if (!(TheDataPlot.GetStreamType() == PlotPairs)) {
		if (!ChannelScale)
			ChannelScale = &(TheDataPlot.GetScaleY(0));
		// LogForm("Got Channel Scale = 0x%x", (long) ChannelScale);
		if (ChannelScale->GetPlotScale() == PlotScaleFixed) 
			Word = ChannelScale->DoScale(Word);
	}
	CheckBuffer(Channel);
	if (Word > (MachWord)(MachWordCast) 32767) Word = (MachWordCast) 32767 ;
	else if (Word < (MachWord)(MachWordCast) -32767) Word =
		(MachWordCast) -32767 ;
	DataBufPtrs[Channel][NextWordInBuf[Channel]++] = Word ;
	CheckBuffer(Channel);
#else
	DbgError("PlotNode::WriteDataWord","only X interface");
#endif
}

void PlotNode::WriteDataPacket()
{

}



