/*
 *  plotdat.h from ObjectProDSP 0.2
 *  Copyright (C) 1994 1995, 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.
 */
#ifndef PLOTDAT_DOT_H
#define PLOTDAT_DOT_H
/*  plotdat.h   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */

#include "ObjProDSP/portable.h"
#include "ObjProComGui/cgidbg.h"
#include "ObjProDSP/attrib.h"
#include "ObjProDSP/arthtyp.h"
#include "ObjProDSP/pltenm.h"

enum PlotScale {PlotScaleAuto,PlotScaleFixed,PlotScaleRangeAuto} ;
// Fixed scaling requires Min and Max to be set to the lower and
// and upper limits of the displayed data.

// Auto scaling in the Y dimension uses the Min Max values of the
// existing data and replots whenever Data is added that execeeds
// the previous Min/Max values 

// Auto scaling in the X dimension keeps squeezing and replotting the
// data as more accumulates

enum LabelingPlotType {LabelingNone,LabelingLinear,LabelingLogarithmic} ;
// NOT IMPLEMENTED YET
// Logartihmic labeling may never be implemented here, rather the
// the log of the data will be taken prior to entering the plotting node.

enum PlotPaging {PlotPagingNone, PlotPagingNewPlot, PlotPagingWrap,
	PlotPagingOnePage} ;
// NOT IMPLEMENTED YET

// With no plot paging the the data simply continuously wraps around
// the plot

// With plot paging new plot the user is prompted to type return to
// continue plotting. As soon as he does so the previous plot is erased/

// With plot paging wrap the user is prompted but only the data to
// be overwritten with new data is erased once the users responds.

// With PlotPagingOnePage all data is scaled to fit on one page.
// With Auto Scaling on the X axis the data will be plotted one
// sample pixel until the plot fills and then it will be rescaled
// with each new block of data.

enum PlottingStreamType {PlotYs, PlotPairs};
// NOT IMPLEMENTED YET

// Stream Of Y's is sequential data, with Coordinate pairs each data
// element speciys both the X and Y coordinates to plot

enum PlotFading {PlotWrapErase, PlotNoFading, PlotPageFading, PlotPointFading};
// NOT IMPLEMENTED YET

// With PlotWrapErase all data that wraps around the plot causes the
// previous data in that position to be erased. With NoFading the
// data accumulates continuously, With PlotPageFading the data
// fades based on the number of pages since the data appeared.
// With PlotPointFading the data fades based on the number of points
// that have been plotted.


const NoMinMax = -0x80000000 ;

/*
 *	Similar data structures are used to specify scaling for
 *	both axises. The Y axis has the following hierarchy of scaling
 *	determinants. For PlotScaleFixed scaling, Max and Min determine the
 *	scaling limits. (PlotMin and PlotMax are the actual limits when the user
 *	interactively rescales the Y Axis.) 
 *	If Scaling is PlotScaleAuto then the current limits of data are
 *	used to determine axis limits. PlotScaleRangeAuto does auto scaling
 *	up to limits and is fixed scaling if data exceeds these limits. 
 *	(This latter case is not implemented yet.)
 */

#define AxisScalingYMembers 			\
	PlotScale Scale ;			\
	double Max;  				\
	double Min;  				\
	int16 LabelParameterSize;		\
	LabelingPlotType Label			\

struct StrAxisScalingY {
	AxisScalingYMembers ;
	void * operator new(unsigned int);
} ;

class AxisScalingY {
friend class PlotChannel ;
friend class DataPlot ;
friend class DataPlotHeader ;
	AxisScalingYMembers ;
	char * LabelParameter ;
public:
	void * operator new(unsigned int);
#undef AxisScalingYMembers
	AxisScalingY(PlotScale scale, double maximum, double minimum,
		LabelingPlotType label, int16 size=0,const char * label_parameter=0);
	AxisScalingY() ;
	AxisScalingY(StrAxisScalingY& Y);
	StrAxisScalingY& GetStructure() {
		StrAxisScalingY& Y = *(new StrAxisScalingY);
		Y.Scale = Scale ;
		Y.Max = Max ;
		Y.Min = Min ;
		Y.Label = Label ;
		Y.LabelParameterSize = LabelParameterSize ;
		return Y;
	}
			
	~AxisScalingY() ;
	void Init() {LabelParameter=0;}
	void SetLabelParameter(const char * label_parameter) ;
	void CopyLabelParameter(int Size,const char * label_parameter) ;
	int GetLabelSize() const {return LabelParameterSize;}
	PlotScale GetPlotScale() const {return Scale;}
	void SetMinimum(double Val) {Min = Val;}
	void SetMaximum(double Val) {Max = Val;}
	void SetScaleType(PlotScale scale) {Scale = scale;}
	double GetMinimum() const { return Min;}
	double GetMaximum() const { return Max;}
	// double GetPlotMinimum() {return PlotMin;}
	// double GetPlotMaximum() {return PlotMax;}
	// void SetPlotMinimum(double Val) {PlotMin = Val;}
	// void SetPlotMaximum(double Val) {PlotMax = Val;}
	int16 DoScale(double Value);
	void Dump();
	int Differ(AxisScalingY& Compare);
	void SetScaling(AxisScalingY& Sc);
	int Rescale(int32 Y0, int32 Y1, double MinY, double MaxY, int Expand);
	inline int16 DoScale(double Value, double& DoScaleReturn) ;
} ;

// BlockRateFactor for X axis scaling determines the relationship
// between X axis labeling and the SamplingRate. 
// It is a simple scaling factor indicating the relationship between
// the block index (sample index for 1-D data), and the sample rate.
// If it is 0 then the
// sampling rate is ignored and the X axis gives the block (or sample) index.
// If it is 1.0 (the normal case) the sampling rate is multiplied
// the block index to get the label value. Thus for nonzero value
// the X axis label is the product of the sample index, the sampling
// rate and this factor.
//
// For two dimensional data there is as similar SampleRateFactor.
// Again, if it is 0 there is no relation between the sampling rate
// and the axis labeling. Otherwise the range of values between
// Max and Min is equal to this value times the sampling rate.


#define AxisScalingXMembers				\
	PlotScale Scale ;				\
	double Max;  					\
	double Min;  					\
	double BlockRateFactor;				\
	PlotFading Fading ;				\
	PlotPaging Paging ;				\
	double SamplesPerPlot ; 				\
	int16 PlotsPerPage ;				\
	int16 LabelParameterSize;			\
	LabelingPlotType Label				\

struct StrAxisScalingX {
	AxisScalingXMembers ;
	void * operator new(unsigned int);
} ;
	
class AxisScalingX {
friend class DataPlot ;
friend class DataPlotHeader ;
	AxisScalingXMembers ;
	char * LabelParameter ;
public:
	void * operator new(unsigned int);
#undef AxisScalingMembers
	AxisScalingX(PlotScale scale, double maximum, double minimum,
		LabelingPlotType label, int16 size=0,const char * label_parameter=0,
		PlotPaging paging = PlotPagingWrap,
		PlotFading fading = PlotWrapErase, int32 samples_in_page = 0,
		int16 plots_per_page=1) ;
	AxisScalingX() ;
	AxisScalingX(StrAxisScalingX& X) ;
	~AxisScalingX() ;
	StrAxisScalingX * GetStructure() ;
	void Init() {LabelParameter=0;}
	void SetLabelParameter(const char * label_parameter) ;
	void CopyLabelParameter(int Size,const char * label_parameter) ;
	int GetLabelSize() const {return LabelParameterSize;}
	PlotFading GetFading() const {return Fading ;}
	void SetFading(PlotFading fade) {Fading =fade;}
	PlotPaging GetPaging() const {return Paging ;}
	void SetPaging(PlotPaging paging) {Paging = paging;}
	double GetSamplesPerPlot() const {return SamplesPerPlot;} 
	void SetSamplesPerPlot(double samples) {SamplesPerPlot = samples;}
	int32 GetPlotsPerPage() const {return PlotsPerPage;}
	void SetPlotsPerPage(int16 plots) {PlotsPerPage = plots;}
	PlotScale GetPlotScale() const {return Scale;}
	void SetMinimum(double Val) {Min = Val;}
	void SetMaximum(double Val) {Max = Val;}
	double GetMinimum() const { return Min;}
	double GetMaximum() const { return Max;}
	// void SetPlotMinimum(double Val) {PlotMin = Val;}
	// void SetPlotMaximum(double Val) {PlotMax = Val;}
	// double GetPlotMinimum() { return PlotMin;}
	// double GetPlotMaximum() { return PlotMax;}
	double GetIncrementPerSample() ;
	double GetBlockRateFactor() const {return BlockRateFactor;}
	void SetBlockRateFactor(double val) {BlockRateFactor = val;}
	void SetScaleType(PlotScale scale) {Scale = scale;}
	int Rescale(double min, double VirtualWidth, int Expand, int PixelWidth,
		double Rate);
	int Differ(AxisScalingX& Compare);
	void SetScaling(AxisScalingX& Sc) ;
	void Dump();
	int IsTwoDimensionalPlot() ;
	inline int16 DoScale(double Value, double& DoScaleReturn) ;
} ;

const DefaultScaleFactor = 32768 ;

struct StrMultiplexedElement {
	int32 ScaleFactor ;
	int16 Color ;	
	int16 LineType ;
	void Dump();
	void * operator new(unsigned int);
};

class MultiplexedElement {
friend class PlotChannel ;
	int32 ScaleFactor ;
	int16 Color ;	
	int16 LineType ;
public:
	void * operator new(unsigned int);
	MultiplexedElement(StrMultiplexedElement& Elt) {
		ScaleFactor = Elt.ScaleFactor ;
		Color = Elt.Color ;
		LineType = Elt.LineType ;
	}
	MultiplexedElement() {}
	MultiplexedElement(int32 scale,int16 color,int16 line_type)
		{ScaleFactor = scale; Color = color; LineType = line_type;}
	StrMultiplexedElement& GetStructure() {
		StrMultiplexedElement& E = *(new StrMultiplexedElement) ;
		E.ScaleFactor = ScaleFactor ;
		E.Color = Color ;
		E.LineType = LineType ;
		return E ;
	}
	void Dump();
	void SetPlotLineType(class Screen *);
		// should never be called from DSP end
};

// ChannelIndex is used in computing the physical index of a sample
// that may have arbitrary resampling relative to a base channel
// Arbitrary resampling is defined by the ratio if two positive integers
// which for this program must each be less than 32768

struct ChannelIndex {
	int32 Index ;			// physical index into database
	int16 ExactResidue ;		// exact residue
					// (see PlotChannel::ComputSampleIndex)
	int16 NormalizedResidue ;	// approrximate fractional distance
					// this sample is from an exact sample
	ChannelIndex(int32 index, int16 exact, int16 normal) {
		Index = index ;
		ExactResidue = exact ;
		NormalizedResidue = normal;
	}
	void * operator new(unsigned int);
	ChannelIndex() {}
	void Dump();
};

#define PlotChannelMembers			\
	int16 ChannelNumber ;			\
	int16 NumberMultiplexedElements ;	\
	int16 MultiplexedElementToSet ;		\
	int16 NumeratorResamplingFactor ;	\
	int16 DenominatorResamplingFactor ;	\
	int16 ThePlotArithType ;	\
	int32 InputElementSize ;		\
	int32 InputBlockSize ;			\
	double SampleRate ;			\
	double FirstSampleTime ;		\
	double SampleRateFactor

struct StrPlotChannel {
	StrAxisScalingY ScaleY ;
	PlotChannelMembers ;
	void * operator new(unsigned int);
	void Dump();
};

class PlotChannel {
	AxisScalingY ScaleY ;
	PlotChannelMembers ;
	MultiplexedElement * TheMultiplexedElements ;
public :
	void * operator new(unsigned int);
	PlotChannel(AxisScalingY Y,int chan, int16 type )
	{
		ScaleY = Y;
		MultiplexedElementToSet = 0;
		NumberMultiplexedElements = MultiplexedElementToSet = 0;
		NumeratorResamplingFactor = DenominatorResamplingFactor = 1 ;
		TheMultiplexedElements = 0 ;
		ChannelNumber = chan  ;
		ThePlotArithType = type ;
	}
	virtual ~PlotChannel();
	void Init() {ScaleY.Init();TheMultiplexedElements=0;
		MultiplexedElementToSet = 0;ChannelNumber=0; }
	PlotChannel() {Init(); ThePlotArithType=0;}
	PlotChannel(PlotChannel *Chan) {*this = *Chan;}
	PlotChannel(AxisScalingY& Scaling, int16 chan, int16 NumElts,
		int16 Numerator, int16 Denominator, int16 type, int32 InElt,
		int32 InBlock, double rate, double First,
		double sample_rate_factor)
		{Init(); ChannelNumber = chan;
		NumberMultiplexedElements = NumElts;
		NumeratorResamplingFactor = Numerator;
		DenominatorResamplingFactor = Denominator;
		ThePlotArithType = type ;
		SampleRate = rate; FirstSampleTime = First;
		ScaleY = Scaling ; InputElementSize=InElt;
		SampleRateFactor = sample_rate_factor ;
		InputBlockSize=InBlock;}
#define AssignForPlotChannel(X)			\
	D(X,ChannelNumber) ;			\
	D(X,NumberMultiplexedElements) ;	\
	D(X,MultiplexedElementToSet) ;		\
	D(X,NumeratorResamplingFactor) ;	\
	D(X,DenominatorResamplingFactor) ;	\
	D(X,ThePlotArithType) ; \
	D(X,InputElementSize);			\
	D(X,InputBlockSize);			\
	D(X,FirstSampleTime);			\
	D(X,SampleRateFactor);			\
	D(X,SampleRate) 			\
		
	PlotChannel(StrPlotChannel& X) {
		ScaleY = X.ScaleY ;
#define D(x,z) z = x.z
		AssignForPlotChannel(X);
#undef D 
	}

	StrPlotChannel& GetStructure() {
		StrPlotChannel& X = *(new StrPlotChannel);
		X.ScaleY = ScaleY.GetStructure() ;		
#define D(x,z) x.z = z
		AssignForPlotChannel(X);
#undef D
#undef AssignForPlotChannel
		return X;
	}
	void SetLabelParameter(int Size,const char * label_parameter) ;
	void SetMultiplexedElement(StrMultiplexedElement& multiplexed_element) ;
	int GetNumberElements() const {return NumberMultiplexedElements;}
	void InitMultiplexedElements();
	void CheckSet();
	ChannelIndex ComputeSampleIndex(double BaseIndex,int16 BaseNumerator=1,
		int16 BaseDenominator=1,int16 norm_res =0);
	int16 GetNumerator() const {return NumeratorResamplingFactor;}
	int16 GetDenominator() const {return DenominatorResamplingFactor;}
	double GetSampleRate() const {return SampleRate;}
	void SetSampleRate(double NewRate) {SampleRate = NewRate ;}
	double GetSamplingRatio() const ;
	int NotComplete() ;
	double GetFirstSampleTime() {return FirstSampleTime;}
	int32 GetInputElementSize() {return InputElementSize;}
	int32 GetInputBlockSize() {return InputBlockSize;}
	AxisScalingY& GetScaleY() {return ScaleY;}
	virtual void Dump();
	virtual void DumpFull();
	void SetChannelNumber(int chan) {ChannelNumber = chan;}
	int16 GetChannelNumber() const {return ChannelNumber;}
	MultiplexedElement * GetMultiplexedElements() const
		{return TheMultiplexedElements;}
	double GetSampleRateFactor() const {return SampleRateFactor;}
	void SetSampleRateFactor(double val) {SampleRateFactor = val;}
	double DisplaySampleRateFactor(int TimeLabel, int TwoDim);
	ArithType::ArithTypes arith_type() const
		{return (ArithType::ArithTypes) ThePlotArithType;}
};
	

enum DataSpacing {DataSpacingUniform,DataSpacingRandom} ;
	// Random imilies random Y coordinate specified as a mutliplexed
	// element member with color = -1 ; In this case elements are
	// displayed in the sequence recieved
	
	// Uniform implies that the resampling is a rational fraction
	// realative to all other channels - even with `uniform' sampling
	// small nonlinearites can be accomodated by interspercing a
	// reindexing control commands within the data stream. Ordinarily
	// uniform data is a continuous stream of 16 bit integers between
	// -32767 and +32767. The sample value -32768 is a control flag
	// that indicates the next 16 bit word is a control command
	// and the next 32 bits after that is a parameter to that control.
	// The control commands are given in the following enum:

const DataControlFlag = -32768 ;

enum DataControl{DataControlNullNotUsed,DataControlSetSampleIndex,
	DataControlSetSampleFraction,DataControlEndOfFile} ;

#define PlotDataHeaderMembers			\
	AxisScalingX ScaleX ;			\
	int16 PlotIdentifier ;			\
	int ScaleXBaseChannel ;			\
	int16 NumberOfChannels ;		\
	PlottingStreamType StreamType ;		\
	int16 PlotChannelToSet ;		\
	DataSpacing Spacing			\

struct StrDataPlotHeader {
	PlotDataHeaderMembers ;
	void Dump();
	void * operator new(unsigned int);
};

class DataPlotHeader {
	PlotDataHeaderMembers ;
	PlotChannel ** ThePlotChannels ;
	int BaseChannel ;
	const char * Caption ;
public:
	void * operator new(unsigned int);
#undef PlotDataHeaderMembers
	PlotChannel ** AllocPlotChannels() ;
	DataPlotHeader(int16 id, int16 NumChan, AxisScalingX& X,
		PlottingStreamType streaming,
		DataSpacing spacing,const char * capt=0) ;
	DataPlotHeader(StrDataPlotHeader& X) ;
	virtual ~DataPlotHeader();
	void DoInit();
	StrDataPlotHeader * GetStructure() ;
	void Init() {ThePlotChannels = 0; PlotChannelToSet = 0; };
	virtual PlotChannel& MakePlotChannel(StrPlotChannel& channel) ;
	int GetPlotChannelToSet() const {return PlotChannelToSet;}
	PlotChannel ** GetThePlotChannels() const {return ThePlotChannels;}
	PlotChannel * GetPlotChannel(int i) const {return ThePlotChannels[i];}
	DataPlotHeader() {ScaleX.Init(); Init();}
	DataPlotHeader(DataPlotHeader * Hd) {*this = *Hd;}
	const char * GetCaption() {return Caption ;}
	void SetCaption(const char * capt) {Caption = capt;}
	void SetPlotChannel(StrPlotChannel& channel) ;
	void SetLabelParameter(int Size,const char * label_parameter) ;
	void SetMultiplexedElement(StrMultiplexedElement& multiplexed_element) ;
	int16 GetNumberOfChannels() const {return NumberOfChannels;}
	int16 GetPlotIdentifier() const {return PlotIdentifier;}
	AxisScalingX& GetScaleX() {return ScaleX;} ;
	AxisScalingY& GetScaleY(int i = 0)
		{return GetPlotChannel(i)->GetScaleY();}
	void SetScaleX(AxisScalingX& Sca) ;
	void SetScaleY(AxisScalingY& Sca, int Channel= 0);
	PlottingStreamType GetStreamType() const {return StreamType ; }
	int GetScaleXBaseChannel() const {return ScaleXBaseChannel ;}
	void SetScaleXBaseChannel(int Channel) {ScaleXBaseChannel = Channel;}
	PlotChannel * GetChannel(int Channel);
	double GetFirstSampleTime();
	double GetHighestSampleRate();
	int32 GetInputElementSize(int Channel);
	int32 GetBaseChannelElementSize();
	int GetBaseChannel() ;
	void SetBaseChannel() ;
	virtual void Dump();
	virtual void DumpFull();
	double DisplaySampleRateFactor(int Channel, int TimeLabel=0);
	static void * clear_new(int size);
};


// DataPlotHeader and the structures it references are sent
// via packets from DSP code to GUI code to describe a plot prior
// to transmitting any data to plot.

// Codes for gloabal plot control messages
enum PlotControlOptions {PlotControlGetId, PlotControlSendId} ;

// Code for control options for a specific plot
extern double LargeDouble ;

inline int16 DoScale(double Min, double Value, double Max,
	double& DoScaleReturn)
{
	if (Max - Min <= 0.0) DbgError("AxisScaling::DoScale","Max Min bad");
	DoScaleReturn = (Value - Min) * (65534. / (Max - Min)) - 32767. ;
	if (DoScaleReturn < -32767.) DoScaleReturn = - 32767. ;
	if (DoScaleReturn > 32767.) DoScaleReturn = 32767. ;
	return (int16) DoScaleReturn ;
}

inline int16 AxisScalingX::DoScale(double Value, double& DoScaleReturn)
{
	return ::DoScale(Min,Value,Max,DoScaleReturn);
}

inline int16 AxisScalingY::DoScale(double Value, double& DoScaleReturn)
{
	return ::DoScale(Min,Value,Max,DoScaleReturn);
}

#endif /* #ifdef PLOTDAT_DOT_H */

