/*
 *  cxcos.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 "ObjProGui/sigintfc.h"
#include "ObjProNet/dfnode.h"

#include "ObjProUsr/cxcos.h"
#include "ObjProGen/outtok.h"
#include "ObjProGui/intfc.h"
#include "ObjProGui/remmen.h"
#include "ObjProGui/user.h"
#include "ObjProGui/dynmnu.h"
#include "ObjProArith/typout.h"
#include "ObjProGui/array.h"
#include "ObjProGui/interinit.h"
#include "ObjProGen/stattyp.h"
#include "ObjProComGui/cgidbg.h"
static EntityList * CxCosNodeList = 0 ;
static InteractiveEntity * IntEntCxCos ;
void CxCosNodesInit();
CxCos::CxCos (const char * Name, double Frequency, double Phase, double Amplitude):
	Signal(Name, 1, 2, 1, 1, TimingTypeLinear, 
	(ArithType::ArithCapabilities)ArithType::ArithTypeUndefined)
,
	Frequency_1(Frequency),
	Phase_2(Phase),
	Amplitude_3(Amplitude)
{
	if (!CxCosNodeList) CxCosNodesInit() ;
	CxCosNodeList->Append(MakeDeclaredEntity(this, IntEntCxCos)) ;
	InitArithType(TheArithType);
	NewMenuItem("CxCos",GetName());
#line 48 "../cxcos.usr"
 
	CurrentIndex = 0;
#line 42 "../cxcos.C"
} // end constructor

CxCos::~CxCos()
{
	TheMenuServer->DeleteMenuItem("CxCos",GetName());
	CxCosNodeList->Delete(GetName()) ;
} // end destructor

int CxCos::CheckSafeDelete()
{
	int Safe_Check_Return = DfNode::CheckSafeDelete();
	if (!Safe_Check_Return) return 0;
	return 1;
} // end check safe delete

double CxCos::TimeFirst( DfNodeInLink * , DfNodeOutLink * )
{
#line 65 "../cxcos.usr"
	return 0.0 ;
#line 62 "../cxcos.C"
} // end timing code

CxCos * CxCosDef;

ErrCode CxCos::DoNode(int32 k)
{
#line 72 "../cxcos.usr"
 
	for (int32 i = 0 ; i < k ; i++ ) {
		double Phase = GetPhase() + GetFrequency() * CurrentIndex++ ;
		double RealPart = GetAmplitude() * cos (Phase);
		MachWord Value = (MachWordCast) RealPart ;
		WriteWord(Value) ;
		double ImagPart = GetAmplitude() * sin (Phase);
		Value = (MachWordCast) ImagPart ;
		WriteWord(Value) ;
	}
	return OK ;
#line 81 "../cxcos.C"
} // end kernel code

static UserEntity * MakeCxCos(OutTokens& Out, EntityReq Request,
	InteractiveEntity& IntNode,
	ArithType::ArithCapabilities arith = (ArithType::ArithCapabilities) TheArithType) ;
int CxCos::CppList(OutTokens& Out, CppListCmds Cmd)
{
	return IntEntCxCos->CppList(Out,Cmd,this);
}

void CxCos::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeCxCos(Out,EntityReqDescribeFull,*IntEntCxCos,TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("Frequency");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetFrequency()));
		Out.NextFillOut(")");
		Out.NextFillOut("specifies the signal frequency in radians per");
		Out.NextFillOut("sample. In other words the phase of a given sample is");
		Out.NextQuoteOut("Frequency");
		Out.NextFillOut("radians plus the phase of the previous sample.");
		Out.NextQuoteOut("Phase");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetPhase()));
		Out.NextFillOut(")");
		Out.NextFillOut("specifies the initial phase of the first sample");
		Out.NextFillOut("of the signal.");
		Out.NextQuoteOut("Amplitude");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetAmplitude()));
		Out.NextFillOut(")");
		Out.NextFillOut("specifies the maximum amplitude of the continuous");
		Out.NextFillOut("cosine function. This may not be the maximum");
		Out.NextFillOut("amplitude of the samples generated. If the");
		Out.NextFillOut("function is sampled at a phase that is an integer multiple");
		Out.NextFillOut("of Pi, then the samples will obtain this maximum.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntCxCos->GetOneParameter("Frequency")->
			FloatP->CurrentValue = Frequency_1;
		IntEntCxCos->GetOneParameter("Phase")->
			FloatP->CurrentValue = Phase_2;
		IntEntCxCos->GetOneParameter("Amplitude")->
			FloatP->CurrentValue = Amplitude_3;
		break;
	}
} // end  list entity switch

static ValueType * SetFrequency(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				double Frequency =
			Param->GetFloatParameterValue("Frequency");
		((CxCos *) This)->SetFrequency(Frequency);
		return 0 ;
	}
	}
	return 0;
}

static ValueType * SetPhase(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				double Phase =
			Param->GetFloatParameterValue("Phase");
		((CxCos *) This)->SetPhase(Phase);
		return 0 ;
	}
	}
	return 0;
}

static ValueType * SetAmplitude(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				double Amplitude =
			Param->GetFloatParameterValue("Amplitude");
		((CxCos *) This)->SetAmplitude(Amplitude);
		return 0 ;
	}
	}
	return 0;
}

void CxCosNodesInit()
{
	if (CxCosNodeList)  return ;

	static StringParam CxCosNameParam =
		{"CxCos", MakeNewEntityName, 0, LegalEntityName};
	static FloatParam CxCosFrequencyParam = {
		 0.125663706144, 0,  0,  -3.1416,  0,  3.1416};
	static FloatParam CxCosPhaseParam = {
		 0.0, 0,  0,  -6.2832,  0,  6.2832};
	static FloatParam CxCosAmplitudeParam = {
		 1024., 0, 0, -1e+100, 0, 1e+100};

	static OneParameter CxCosParArray[] = {
		{"Name", 0, "node name", 0, 0, &CxCosNameParam},
		{"Frequency", 0, 
			"frequency (in radians per sample)",
			0, &CxCosFrequencyParam},
		{"Phase", 0, 
			"phase (in radians) of first sample",
			0, &CxCosPhaseParam, 0, 0, 0, 1},
		{"Amplitude", 0, 
			"absolute maximum amplitude of the continuous cosine function",
			0, &CxCosAmplitudeParam, 0, 0, 0, 1},
		{0}
	};

	static OneParameter SetFrequencyCxCosList[] = {
		{"Frequency", 0, "frequency (in radians per sample)",
			 0, &CxCosFrequencyParam},
			{0}
	};
	UserParameters * SetFrequencyMemberParam = new UserParameters
		(SetFrequencyCxCosList);

	Procedure * SetMemberProcFrequency = new Procedure("SetFrequency", SetFrequency,
		 SetFrequencyMemberParam, "void");
	static OneParameter SetPhaseCxCosList[] = {
		{"Phase", 0, "phase (in radians) of first sample",
			 0, &CxCosPhaseParam, 0, 0, 0, 1},
			{0}
	};
	UserParameters * SetPhaseMemberParam = new UserParameters
		(SetPhaseCxCosList);

	Procedure * SetMemberProcPhase = new Procedure("SetPhase", SetPhase,
		 SetPhaseMemberParam, "void");
	static OneParameter SetAmplitudeCxCosList[] = {
		{"Amplitude", 0, "absolute maximum amplitude of the continuous cosine function",
			 0, &CxCosAmplitudeParam, 0, 0, 0, 1},
			{0}
	};
	UserParameters * SetAmplitudeMemberParam = new UserParameters
		(SetAmplitudeCxCosList);

	Procedure * SetMemberProcAmplitude = new Procedure("SetAmplitude", SetAmplitude,
		 SetAmplitudeMemberParam, "void");
static ValueType * CxCosMembers[4] ;
	int ii = 0 ;
	CxCosMembers[ii++] = new ValueType(DecProcedure, SetMemberProcFrequency) ;
	CxCosMembers[ii++] = new ValueType(DecProcedure, SetMemberProcPhase) ;
	CxCosMembers[ii++] = new ValueType(DecProcedure, SetMemberProcAmplitude) ;
	CxCosMembers[ii++] = 0 ;
	CxCosNodeList = new EntityList;
	IntEntCxCos = new InteractiveEntity("CxCos", CxCosNodeList,
		MakeCxCos, InteractiveSignal, "cxcos.h",
		CxCosMembers, "Signal");
	IntEntCxCos->SetParameters(new UserParameters(CxCosParArray));
	TheNodes->Append(IntEntCxCos);
	new CxCos("CxCos8", 0.78539816339744830961, 0.0, 1024.);
} // end initalization

static UserEntity * MakeCxCos(OutTokens& Out, EntityReq Request,
	InteractiveEntity& IntNode,
	ArithType::ArithCapabilities arith)
{
	switch(Request) {
case EntityReqDescribe:

case EntityReqDescribeFull:
		Out.NextQuoteOut("CxCos");
		Out.NextFillOut("generates the sampled complex function:");
		Out.NextQuoteOut("Amplitude");
		Out.NextFillOut("e^(2 Pi i(");
		Out.NextFillOutConcat("Phase");
		Out.NextFillOut("+ N");
		Out.NextQuoteOut("Frequency");
		Out.NextFillOutConcat(")).");
		Out.NextFillOut("N is the sample index.  It starts at 0.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		double Frequency =
			IntNode.GetFloatParameterValue("Frequency");
		double Phase =
			IntNode.GetFloatParameterValue("Phase");
		double Amplitude =
			IntNode.GetFloatParameterValue("Amplitude");
		return new CxCos(Name, Frequency, Phase, Amplitude);

	}
	}
	return 0;
}

static InitObj LocalInit(CxCosNodesInit, "CxCos", "Signal");

