// =====================================================
//
//   miniLA_win - Decoder Datastream routines
//
//   routines provides additional functions to routines
//   in DataHold
//
//   (c) miniLA Team
//
// =====================================================
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This software 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 the GNU General Public License
// along with this package; see the file COPYING.  If not, write to
// the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.


unit uDecData;

interface

var
   sample		: cardinal;			// sample value
   sample_inv		: cardinal;			// sample inverter
   sample_n		: int64;                        // sample number (position, relative)
   time_p		: double;			// time pointer (relative)


procedure data_init(start, stop : int64);		// absolute values of sample (without trigger pos)
function data_find_value(value :cardinal; mask:cardinal) : boolean;
function data_get_value(time_s:double) : boolean;
function data_find_change(mask:cardinal) : boolean;


implementation

uses
   dlgMain,
   uDisplay;

var
   stop_ptr		: int64;			// last sample number (absolute)
   timestep		: double;


//==========================================================
// Initialize
//==========================================================
procedure data_init(start, stop : int64);
var start_ptr: int64;
begin
   if start < stop then
    begin
      start_ptr := start;
      stop_ptr := stop;
    end
   else
    begin
      start_ptr := stop;
      stop_ptr := start;
    end;

   if start_ptr < 0 then
      start_ptr := 0;
   if stop_ptr > frmMain.LogPanel.Display.DataHold.MaxPosition then
      stop_ptr := frmMain.LogPanel.Display.DataHold.MaxPosition;

   sample:=frmMain.LogPanel.Display.DataHold.GetSampleValue(start_ptr) xor sample_inv;
   timestep:= 1/frmMain.LogPanel.Timebase;
   sample_n := frmMain.LogPanel.Display.DataHold.Position-frmMain.LogPanel.Cursors[2].Position;
   time_p := sample_n * timestep;
end;


//==========================================================
// Start searching next samples for given value
//==========================================================
function data_find_value(value :cardinal; mask:cardinal) : boolean;
var
   read_err 	: boolean;
begin
   read_err := false;

   if frmMain.LogPanel.Display.DataHold.Position < frmMain.LogPanel.Display.DataHold.MaxPosition then
      sample:=frmMain.LogPanel.Display.DataHold.GetSampleValue(frmMain.LogPanel.Display.DataHold.Position+1) xor sample_inv
   else
      read_err := true;

   while ((((frmMain.LogPanel.Display.DataHold.Sample xor sample_inv) and mask) <> value) and not(read_err)) do
      read_err := not(frmMain.LogPanel.Display.DataHold.FindChange(mask, stop_ptr, true));

   sample := frmMain.LogPanel.Display.DataHold.Sample xor sample_inv;
   sample_n := frmMain.LogPanel.Display.DataHold.Position-frmMain.LogPanel.Cursors[2].Position;
   time_p := sample_n * timestep;
   result := read_err;
end;

//==========================================================
// Get value for specific time
//==========================================================
function data_get_value(time_s:double) : boolean;
var
   pos		: int64;
begin
   pos := round(time_s/timestep+frmMain.LogPanel.Cursors[2].Position);
   if (pos>=0) and (pos <= frmMain.LogPanel.Display.DataHold.MaxPosition) then
    begin
      sample := frmMain.LogPanel.Display.DataHold.GetSampleValue(pos) xor sample_inv;
      sample_n := frmMain.LogPanel.Display.DataHold.Position-frmMain.LogPanel.Cursors[2].Position;
      time_p := sample_n * timestep;
      result := false;
    end
   else
      result := true;	// out of range
end;


//==========================================================
// Look for sample change
//==========================================================
function data_find_change(mask:cardinal) : boolean;
begin
   result := not(frmMain.LogPanel.Display.DataHold.FindChange(mask, stop_ptr, true));
   // returned value only for unmasked values, we need all signals
   sample := frmMain.LogPanel.Display.DataHold.GetSampleValue(frmMain.LogPanel.Display.DataHold.Position) xor sample_inv;
   sample_n := frmMain.LogPanel.Display.DataHold.Position-frmMain.LogPanel.Cursors[2].Position;
   time_p := sample_n * timestep;
end;

end.
