/*
 *  plotdatg.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.
 */
/*  plotdatg.h   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */
#ifndef PLOTDATG_DOT_H
#define PLOTDATG_DOT_H
#include "dlist.h"
#include "slist.h"


#include "rel_pos.h"
#include "plotdat.h"
#include "shared.h"
#include "iv_graph.h"

class ivWindow ;
class Graph ;

const NotInitialized = -0x80000000 ;

class DataPlot ;


class DataPlotList: public SingleList {
public:
    ErrCode Insert(DataPlot *nt) {return SingleList::Insert(nt);}
    ErrCode Append(DataPlot *nt) {return SingleList::Append(nt);}
    DataPlot * Get()   {return (DataPlot *) SingleList::Get();}
    DataPlot * Pop() {return (DataPlot *) SingleList::Pop();}
    DataPlotList(){;}
    int Size(){return SingleList::Size();}
	void RemoveEntry(DataPlot * rem) {SingleList::RemoveEntry((void *) rem);}
	void adjust_adjuster() ;
	void raise_window(int plot_id);
} ;

class DataPlotListIterator:private SingleListIterator {
public:
    DataPlotListIterator(DataPlotList& df):
		SingleListIterator((SingleList&) df){}
    DataPlot * operator()()
        {return (DataPlot *) Next();}
};


struct TimingCorrection {
	int32 NewBaseSampleIndex ;
	int32 PhysicalIndexOfNewBaseSample ;
	int32 FractionalOffset ;
	TimingCorrection(){}
	TimingCorrection(int32 base, int32 physical, int32 frac)
	{
		NewBaseSampleIndex = base;
		PhysicalIndexOfNewBaseSample = physical;
		FractionalOffset = frac ;
	}
};

class TimingCorrectionList: public DoubleList {
public:
	ErrCode Insert(TimingCorrection *nt) {return DoubleList::Insert(nt);}
	ErrCode Append(TimingCorrection *nt) {return DoubleList::Append(nt);}
	TimingCorrection * Pop(){return(TimingCorrection *) DoubleList::Pop();}
	TimingCorrection * GetLast()
		{return (TimingCorrection *) DoubleList::GetLast();}
	TimingCorrectionList(){}
	int Size(){return DoubleList::Size();}
} ;

class TimingCorrectionListIterator: public DoubleListIterator {
public:
	TimingCorrectionListIterator(TimingCorrectionList& df):
		DoubleListIterator((DoubleList&) df){}
	TimingCorrection * operator()()
		{return (TimingCorrection *) Next();}
};

class TimingCorrectionListBackIterator: public DoubleListIterator {
public:
	TimingCorrectionListBackIterator(TimingCorrectionList& df):
		DoubleListIterator((DoubleList&) df){}
	TimingCorrection * operator()()
		{return (TimingCorrection *) Previous();}
};

enum ActiveControlState {ActiveControlInactive,ActiveControlReadFlag,
	ActiveControlReadWord, ActiveControlData1};

class PlotChannelPointer : public PlotChannel {
	TimingCorrectionList TimingCorrections ;

	int32 NextBlockToPlot ;   // Negative times correspond to data
				  // that does not exist (and thus is
				  // not displayed. This happens when
				  // the data for multiple channels
				  // does not all start at the same time.
	int32 NextSampleOffset ;  // position within block to begin plot

	int32 NextDataToWrite ;

	double * LastXPlotted;
	double * LastYPlotted;

	double MaxYVal;
	double MinYVal;
	double MaxXVal; 		// MinX and MaxX are only used for eye plots
	double MinXVal;

	double OldMaxYVal;
	double OldMinYVal;
	double OldMaxXVal;
	double OldMinXVal;

	class DataPlot * ThePlot ;
	class DataFile * the_data_file ;
	int Index ;		// PlotChannelIndex

	class PlotInfo * LastPlotInfo ;
	AxisScalingY OriginalScaleY ;


	double SampleRateAdjustment ;

	int32 PhysicalSampleIndex() ;
	void DoInit() ;
public:
	PlotChannelPointer() ;
	PlotChannelPointer(class StrPlotChannel& Chan,int transform,
		PlotChannelPointer* cloned_from);
	void clone(int plot_id);
	virtual ~PlotChannelPointer();
	void UpdateMax(int i, double val);
	void UpdateData(int32 Size, const char * PlotDataBlock);
	int32 ComputeDataAvailable(int16 Numerator, int16 Denominator);
	void Read(int Size,double * Data, long Where=-1) ;
	void WriteData(int Size,char * Data) ;
	int AdjustSampleRate(double NewRate);
	class DataFile * GetDataFile();
	int size_of() const ;


	int convert_read(int Size, double * data, long where = -1);
	int GetIndex() {return Index;}
	void SetIndex(int inx) {Index = inx;}
	void SetPlot(DataPlot * plt)  ;
	DataPlot * GetPlot() {return ThePlot;}
	void DoPlotData(int32 PixelBase, int32 PixelIncrement, int32 IndexEnd,
		int32 skip=0) ;
	void FetchAndPlotXYData(int32 Begin, int32 End) ;
	void PlotXYData(int32 EndTime) ;
	void PlotData(double EndTime, double BaseIncrement) ;
	void PlotBlockData(int32 IndexEnd) ;
	double IndexToTime(double) ;
	double GetTimeFactor() ;
	double TimeToIndex(double Time) ;
	int32 ThisChannelIndex(int32 BaseChannelIndex) ;
	void Reset(double Time) ;
	int IsRescalingNeeded() ;
	virtual void Dump();
	virtual void DumpFull();
	double GetSampleRateFactor() ;
	double GetMaxXVal() const {return MaxXVal;}
	double GetMinXVal() const {return MinXVal;}
	double GetMaxYVal() const {return MaxYVal;}
	double GetMinYVal() const {return MinYVal;}
	// int ChangeYScale(int32 Y0,int32 Y1,int Expand) ;
	int RestoreOriginalYScaling();
	AxisScalingY& GetOriginalScaleY() {return OriginalScaleY ;}
	double GetPlotMaximum() ;
	double GetPlotMinimum() ;
	double GetSampleRateAdjustment() const {return SampleRateAdjustment ;}
	double GetBaseSampleRate() const ;
	double GetAdjustedSampleRate() const ;
	void SeekToSample(int32 SampleIndex) ;
	void set_from_clone(PlotChannelPointer * cloned_from);
} ;



// Note: PlotBufferSize MUST be larger than ReadBufferSize
const PlotBufferSize = 300 ;
const ReadBufferSize = 256 ;

class DataPlot: public DataPlotHeader {
	const char * Name ;
	// The Base Channel is the one with the highest sampling rate
	int32 BaseChannelNumerator ;
	int32 BaseChannelDenominator ;

	int32 SampleIndexLastPlotUpdate ;
	double NumberSamplesInPlot ;

	int32 LargestIndexAvailableToPlot ;

	int32 PixelWidth ;
		// Screen parameter needed even when there is no screen

	int32 FirstBlockOnCurrentPlot ;
		// This is a sample index into FirstTimeBaseChannel
		// Normaalized by the sampling rate base channel

	// class PlotWindowPreserve * TheWindow ;
	// class PlotWindow * ThePlot ;
	ivWindow * the_window ;
	Graph * the_graph ;

	double BasePixelIncrement ;


	int NextPlotPosition ;
	RelativePosition PlotBuffer[PlotBufferSize];

	double ReadBuffer[ReadBufferSize];

	int WarnedMoreData ;

	AxisScalingX OriginalScaleX ;
	AxisScalingX PreviousScaleX ;

	class PlotFileManager * TheInputFile ;
	int PlotId ;

	int current_channel ;
	int current_element ;
	DataPlotList clones ;
	int first_page_plotted ;

	void ComputeBaseChannel() ;
	PlotChannelPointer * GetPlotChannel(int i) const { return
		((PlotChannelPointer *) DataPlotHeader::GetPlotChannel(i));}
	void ProcessData(int Size, const char * Data, int32 NextChannel) ;
	void ProcessControl(int Size, const char * Data, int32 NextChannel) ;
	void ResetAfterScalingChange() ;
public:
	DataPlot * cloned_from ;
	enum Transform {none,copy,power,db,db_power,spectral} the_transform ;
	DataPlot(class StrDataPlotHeader& Hd, Transform = none);
	DataPlot() ;
	virtual ~DataPlot() ;

	void adjust_adjuster() ;
	void clone(Transform transform);
	int check_init();
	void InitPlotChannels() ;
	PlotChannelPointer * GetChannel(int Channel) { return
		(PlotChannelPointer *) DataPlotHeader::GetChannel(Channel);}
	void Init() ;
	virtual PlotChannel& MakePlotChannel(StrPlotChannel& channel) ;
	int32 ComputeRegionToUpdate();
	void UpdateTickMarks(int32 Index);
	void Reset() ;
	void ResetData() ;
	void Redraw() ;
	void RefreshData();
	void PlotXYBuffer(int32 Size) ;
	void PlotXYData(int32 Index);
	void PlotData(int32 Index);
	void UpdateDisplay() ;
	int NotComplete() ;
	const char * GetName() {return Name;}
	void AddName (const char * Nm) {Name=Nm;}
	const char * GetCaption();
	// void SetWindow(PlotWindowPreserve * win) {TheWindow = win;}
	// PlotWindowPreserve * GetPlotWindow(){return TheWindow;}
	class DataFile * GetDataFile(int Channel);
	void SendComplete();

	void WriteXYPlotBuffer() ;
	void CheckXYPlotBuffer() ;

	void WritePlotBuffer() ;
	void CheckPlotBuffer() ;

	void TwoSamplesLeft() ;
	void PlotOnePoint(double X, double Y, struct PlotInfo& Info) ;
	void FetchAndPlotData(int32 FirstSampleIndex, int32 NumberSamples,
		struct PlotInfo& Info) ;
	double TimeToIndex(double Time) ;
	double IndexToTime(double) ;
	int32 GetPixelWidth() ;
	// void SetPlot(PlotWindow * Plot) {ThePlot = Plot;}
	// PlotWindow * GetPlot() {return ThePlot ;}
	double GetNumberSamplesInPlot() ;
	double GetSampleRateFactor() ;
	double GetDynSampleRate() ;
	int IsRescalingNeeded() ;
	double GetBasePixelIncrement() ;
	double GetBaseOffset();
	double RelVDCToY(int32 Y) ;
	double RelVDCToX(int32 Y) ;
	double RelVDCToTime(int32 Pos) ;
	int32 TimeToVDCPosition(double Time) ;
	int32 FirstSampleOnPlot() ;
	virtual void Dump();
	virtual void DumpFull();
	void NewSampleRate(int Chan, double NewRate);
	PlotChannelPointer * GetSamplingRatioBase() ;
	PlotChannelPointer * GetSampleRateBase() ;
	PlotChannelPointer * GetYScaleBase() ;
	int32 GetFirstBlockOnCurrentPlot() {return FirstBlockOnCurrentPlot;}
	int32 GetBlockSize();
	int16 GetNumerator() ;
	int16 GetDenominator() ;
	double GetSampleRate() ;
	double GetEndTime();
	void CheckNewPage() ;
	void PlotThisPage() ;
	void PlotPage(int32 SampleIndex) ;
	void PageUp() ;
	void PageDown() ;
	void PageEnd() ;
	void PageStart() ;
	void SetPlotFileManager(PlotFileManager * file) {TheInputFile = file;}
	void GoToTime(double time) ;
	void GoToSampleIndex(int32 Index);
	int GetCurrentSample();
	double GetCurrentAddress();
	int GetNumberSamples();
	void DisplayAddress(const char * Name);
	int ChangeXScale(float min,float max,int Expand) ;
	int RestorePreviousXScaling();
	int RestoreOriginalScaling();
	int RestoreOriginalXScaling();
	int RestoreOriginalYScaling(int Channel = 0);
	double GetSampleRateAdjustment(int chan=0) const ;
	double GetAdjustedSampleRate(int chan=0) const ;
	double * GetReadBuffer() const { return ReadBuffer;}
	void set_window(ivWindow *win, Graph * gr);
	Graph *graph() const {return the_graph;}
	ivWindow * window() const {return the_window;}
	int position() { return NextPlotPosition++;}
	void new_window_size();
	void complete();
	int is_eye_plot();
	double GetMaxXVal() const ;
	double GetMinXVal() const ;
	double GetMaxYVal() const ;
	double GetMinYVal() const ;
	double get_min_x_current_plot();
	double get_max_x_current_plot();
	int is_two_dimensional();

	int32 last_sample_index();
	int32 samples_in_plot();
	void plot_sample(int32);
	int32 current_sample();
	int is_first_page_plotted() const {return first_page_plotted;}
	int plot_id() const {return PlotId;}
	void raise_window();
	void set_from_clone();
	const char * transform_name();
};


class PlotManager {
	DataPlotList TheCurrentPlots ;
	DataPlot * PlotToComplete ;
	int NextFreePlotId ;
	void AppendPlot(DataPlot * plot) {TheCurrentPlots.Append(plot);}
public :
	PlotManager(){PlotToComplete = 0; NextFreePlotId = 1; };
	virtual ~PlotManager() ;
	DataPlot * to_complete() const {return PlotToComplete;}
	void AddRemotePlot(int Size, const char * PlotDescription,
		DataPlot::Transform t=DataPlot::none) ;
	void AddRemotePlotCaption(int Size, const char * Data) ;
	void AddRemotePlotName(int Size, const char * Data) ;
	void AddRemotePlotChannel(int Size,
		const char * PlotChannelDescription) ;
	void AddRemoteLabelParameter(int Size,
		const char * PlotLabelParameterDescription) ; 
	void AddRemoteMultiplexedElement
		(int Size, const char * PlotMultiplexedElementDescription) ;
	void UpdateData(int PlotId,int Chan, int Size, const char * Data,
		int Nxt);
	void UpdateControl(int PlotId,int Chan, int Size, const char * Data,
		int Nxt);
	void PlotServer (PacketHeader& Head,const char * Data,
		int32 NextWindow) ;
	int GetPlotId() {return NextFreePlotId++;}
	DataPlot * GetPlot(int16 PlotId);
} ;

extern PlotManager * ThePlotsManager ;
#endif /* #ifdef PLOTDATG_DOT_H */
