#include "ObjProComGui/cgidbg.h"
#include "ObjProGui/sigintfc.h"
#include "ObjProNet/dfnode.h"

#include "ObjProUsr/impulse.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"
static EntityList * CxImpNodeList = 0 ;
static InteractiveEntity * IntEntCxImp ;
void CxImpNodesInit();
CxImp::CxImp (const char * Name, int32 Period, double Phase, double Amplitude, 
		double Width, int32 Transition):
	Signal(Name, 1, 2, 1, 1, TimingTypeLinear, 
	(ArithType::ArithCapabilities)ArithType::ArithTypeUndefined)
,
	Period_1(Period),
	Phase_2(Phase),
	Amplitude_3(Amplitude),
	Width_4(Width),
	Transition_5(Transition)
{
	if (!CxImpNodeList) CxImpNodesInit() ;
	CxImpNodeList->Append(MakeDeclaredEntity(this, IntEntCxImp)) ;
	InitArithType(TheArithType);
	NewMenuItem("CxImp",GetName());
#line 95 "../impulse.usr"
 
	CurrentIndex = 0;
	int16 RealAmp = (int16)(GetAmplitude() * cos (GetPhase()) + .5);
	int16 ImagAmp = (int16)(GetAmplitude() * sin (GetPhase()) + .5);
	PeakSignal = CxMachWord(RealAmp,ImagAmp);
	NullSignal = CxMachWord((int16)0,(int16)0);
	CurrentSignal = NullSignal ;
	ExchSignal = PeakSignal ;
	SampleWidth = (int32) (GetPeriod() * GetWidth() + .5);
	if (SampleWidth < 1) SampleWidth = 1 ;
	NextTransition = GetTransition();
	CurrentPeriodLength = GetPeriod() - SampleWidth;
	if (CurrentPeriodLength < 0) CurrentPeriodLength = 0;
	ExchPeriodLength = SampleWidth ;
#line 49 "../impulse.cxx"
} // end constructor

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

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

double CxImp::TimeFirst( DfNodeInLink * , DfNodeOutLink * )
{
#line 137 "../impulse.usr"
	return 0.0 ;
#line 69 "../impulse.cxx"
} // end timing code

CxImp * CxImpDef;

ErrCode CxImp::DoNode(int32 k)
{
#line 144 "../impulse.usr"
 
	for (int32 i = 0 ; i < k ; i++ ) {
		if (CurrentIndex++ < NextTransition) WriteCxWord(CurrentSignal);
		else {
			// LogOut << "CurrentIndex = " << CurrentIndex << "\n" ;
			CurrentIndex = 1;
			CxMachWord Temp = CurrentSignal ;
			CurrentSignal = ExchSignal ;
			ExchSignal = Temp ;
			int32 Ptemp = CurrentPeriodLength ;
			CurrentPeriodLength = ExchPeriodLength ;
			ExchPeriodLength = Ptemp ;
		
			NextTransition = CurrentPeriodLength ;
			WriteCxWord(CurrentSignal);
		}
	}
	return OK ;
#line 95 "../impulse.cxx"
} // end kernel code

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

void CxImp::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeCxImp(Out,EntityReqDescribeFull,*IntEntCxImp, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("Period");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetPeriod()));
		Out.NextFillOut(")");
		Out.NextFillOut("specifies the number of samples before the");
		Out.NextFillOut("impulse is repeated.");
		Out.NextQuoteOut("Phase");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetPhase()));
		Out.NextFillOut(")");
		Out.NextFillOut("the relative amplitude of the real and imaginary");
		Out.NextFillOut("components of the signal. With");
		Out.NextQuoteOut("Phase");
		Out.NextFillOut("= 0 all the energy");
		Out.NextFillOut("is in the real part. With");
		Out.NextQuoteOut("Phase");
		Out.NextFillOut("= pi/2 all the energy");
		Out.NextFillOut("is in the imaginary part.");
		Out.NextQuoteOut("Amplitude");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetAmplitude()));
		Out.NextFillOut(")");
		Out.NextFillOut("specifies the the magnitude of the impulse");
		Out.NextFillOut("amplitude. It is the square root of the sum of the");
		Out.NextFillOut("squares of the real and imaginary amplitudes.");
		Out.NextQuoteOut("Width");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetWidth()));
		Out.NextFillOut(")");
		Out.NextFillOut("specifies the peak width as a fraction of sample");
		Out.NextFillOut("period.");
		Out.NextQuoteOut("Width");
		Out.NextFillOut("= 0 produces an impulse one sample wide.");
		Out.NextQuoteOut("Width");
		Out.NextFillOut("= 1 results in a constant amplitude and phase signal.");
		Out.NextQuoteOut("Width");
		Out.NextFillOut("= .5 results in a standard square wave.");
		Out.NextQuoteOut("Transition");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetTransition()));
		Out.NextFillOut(")");
		Out.NextFillOut("specifies the sample index where the");
		Out.NextFillOut("first signal transition from 0 occurs. This may be");
		Out.NextFillOut("longer than the sample");
		Out.NextQuoteOut("Period");
		Out.NextFillOutConcat(".");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntCxImp->GetOneParameter("Period")->
			IntP->CurrentValue = Period_1;
		IntEntCxImp->GetOneParameter("Phase")->
			FloatP->CurrentValue = Phase_2;
		IntEntCxImp->GetOneParameter("Amplitude")->
			FloatP->CurrentValue = Amplitude_3;
		IntEntCxImp->GetOneParameter("Width")->
			FloatP->CurrentValue = Width_4;
		IntEntCxImp->GetOneParameter("Transition")->
			IntP->CurrentValue = Transition_5;
		break;
	}
} // end  list entity switch

void CxImpNodesInit()
{
	if (CxImpNodeList)  return ;

	static StringParam CxImpNameParam =
		{"CxImp", MakeNewEntityName, 0, LegalEntityName};
	static IntParam CxImpPeriodParam = {
		 32, 0,  0,  2, 0, 2.14748e+09};
	static FloatParam CxImpPhaseParam = {
		 0.0, 0,  0,  -6.2832,  0,  6.2832};
	static FloatParam CxImpAmplitudeParam = {
		 1024., 0, 0, -1e+100, 0, 1e+100};
	static FloatParam CxImpWidthParam = {
		 .5, 0,  0,  0.0,  0,  1.0};
	static IntParam CxImpTransitionParam = {
		 0, 0,  0,  0, 0, 2.14748e+09};

	static OneParameter CxImpParArray[] = {
		{"Name", 0, "node name", 0, 0, &CxImpNameParam},
		{"Period", 0, 
			"the impulse is repeated after period samples",
			&CxImpPeriodParam},
		{"Phase", 0, 
			"phase (in radians) of first sample",
			0, &CxImpPhaseParam, 0, 0, 0, 1},
		{"Amplitude", 0, 
			"magnitude of impulse amplitude",
			0, &CxImpAmplitudeParam, 0, 0, 0, 1},
		{"Width", 0, 
			"peak width as a fraction of sample period (0=>impulse)",
			0, &CxImpWidthParam, 0, 0, 0, 1},
		{"Transition", 0, 
			"sample index where the first transition occurs",
			&CxImpTransitionParam, 0, 0, 0, 0, 1},
		{0}
	};

	CxImpNodeList = new EntityList;
	IntEntCxImp = new InteractiveEntity("CxImp", CxImpNodeList,
		MakeCxImp, InteractiveSignal, "impulse.h",
		0, "Signal");
	IntEntCxImp->SetParameters(new UserParameters(CxImpParArray));
	TheNodes->Append(IntEntCxImp);
} // end initalization

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

case EntityReqDescribeFull:
		Out.NextQuoteOut("CxImp");
		Out.NextFillOut("generates a periodic impulse or square every");
		Out.NextQuoteOut("Period");
		Out.NextFillOut("samples.");
		Out.NextFillOut("The impulse amplitude is");
		Out.NextQuoteOut("Amplitude");
		Out.NextFillOut("e^(2 Pi i");
		Out.NextQuoteOut("Phase");
		Out.NextFillOutConcat("). The first");
		Out.NextFillOut("transition for 0 to this amplitude occurs at sample");
		Out.NextQuoteOut("Transition");
		Out.NextFillOutConcat(".");
		Out.NextFillOut("The nonzero amplitude is maintained for");
		Out.NextQuoteOut("Width");
		Out.NextFillOut("*");
		Out.NextQuoteOut("Period");
		Out.NextFillOut("samples");
		Out.NextFillOut("where");
		Out.NextQuoteOut("Width");
		Out.NextFillOut("is between 0 and 1.");
		Out.NextFillOut("If");
		Out.NextQuoteOut("Width");
		Out.NextFillOut("= 1.0 then the signal is a constant after the first");
		Out.NextFillOut("transition.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		int32 Period =
			IntNode.GetIntParameterValue("Period");
		double Phase =
			IntNode.GetFloatParameterValue("Phase");
		double Amplitude =
			IntNode.GetFloatParameterValue("Amplitude");
		double Width =
			IntNode.GetFloatParameterValue("Width");
		int32 Transition =
			IntNode.GetIntParameterValue("Transition");
		return new CxImp(Name, Period, Phase, Amplitude, Width, Transition);

	}
	}
	return 0;
}

static InitObj LocalInit(CxImpNodesInit, "CxImp", "Signal");

