unit GHLabXu;
interface
uses
  Classes,
  UlanType, GHLabType;

function ExtDevInit(var AExtDevDrv: PExtDevDrv; const ADesc: shortstring): integer; export;
function ExtDevStart(AExtDevDrv: PExtDevDrv): integer; export;
function ExtDevStop(AExtDevDrv: PExtDevDrv): integer; export;
function ExtDevDoCharIn(AExtDevDrv: PExtDevDrv; ch:char): integer; export;
function ExtDevReadPoint(AExtDevDrv: PExtDevDrv; var APoint: TExpPoint): integer; export;
function ExtDevDone(var AExtDevDrv: PExtDevDrv): integer; export;

implementation
uses
  Fifou, Timer, {x}PropUtl{/x IniFiles};

const
  GHLabBufSlotCount: integer = 1024;
  {x}{/x GHLabPointTimeInterval: single = 31.25;}

type
  TGHLabXDrv = class({x}TComponent{/x TObject})
  private
    FFifo: TFifo;
    FCurVal: integer;
    { currently beeing built Y value from incoming bytes }
    {FCurValPos: byte;}
      { what byte of 2 byte subpkt value is expected to come
        - 0.. first byte, 1 .. second byte}
    FCurTime: single;
    FDesc: shortstring;
    {x}{/x FZeroValue: single;}
    FRunning: boolean;
    {x}
    FYMult: single; // multiply the received number by this one
    FYAdd: single;  // add this number to received one (after multiplying with YMult)
    FPointTimeInterval: single;
    FValByte0Mask: byte;
    FValByte0Shl: shortint;
    FValByte1Mask: byte;
    FValByte1Shl: shortint;
    {/x}
  public
    constructor Create(ADesc: shortstring); reintroduce;
    function Start: integer;
    function Stop: integer;
    destructor Destroy; override;
    function DoCharIn(ch:char): integer;
    function ReadPoint(var APoint: TExpPoint): integer;
  published
    property YMult: single read FYMult write FYMult;
    property YAdd: single read FYAdd write FYAdd;
    property PointTimeInterval: single read FPointTimeInterval write FPointTimeInterval;
    property ValByte0Mask: byte read FValByte0Mask write FValByte0Mask;
    property ValByte0Shl: shortint read FValByte0Shl write FValByte0Shl;
    property ValByte1Mask: byte read FValByte1Mask write FValByte1Mask;
    property ValByte1Shl: shortint read FValByte1Shl write FValByte1Shl;
  end;


constructor TGHLabXDrv.Create(ADesc: shortstring);
begin
  inherited Create(nil);
  {x}
  FYMult := 1;
  FYAdd := 0;
  FPointTimeInterval:= 40;
  FValByte0Mask := $7F;
  FValByte0Shl := 0;
  FValByte1Mask := $07;
  FValByte1Shl := 7;

  Name := ADesc;
  {/x}
  FDesc := ADesc;
  FFifo := TFifo.Create(sizeof(TExpPoint), GHLabBufSlotCount);
  {x}
  ClassReadWriteIniFile(Self, 0, '', true);
  {/x}
end;


function TGHLabXDrv.Start: integer;
begin
  Result := 0;
  FCurTime := 0;
  FFifo.Clear;
  FRunning:= true;
end;

function TGHLabXDrv.Stop: integer;
begin
  Result := 0;
  FRunning := false;
end;

destructor TGHLabXDrv.Destroy;
begin
{x}
  ClassReadWriteIniFile(Self, 0, '', false);
{/x}
  FFifo.Free;
  inherited Destroy;
end;

function TGHLabXDrv.DoCharIn(ch:char): integer;
var
  b: byte absolute ch;
  ep: TExpPoint;
begin
  {
  0. byte:
      7 bit - 0;
      0..6 bit - 0..6 bit of VALUE
  1. byte:
      7 bit - 1;
      3..6  - citac
      0..2 bit - 7..9 bit of VALUE

  4800,8,N,1,DTR+,RTS+
  }
  if FRunning then begin
    Result := 0;
    if (b and  $80) <> 0 then begin
      {x}
      FCurVal := FCurVal or (word(b and ValByte1Mask) shl ValByte1Shl);

      ep.X := FCurTime / 1000;
      FCurTime := FCurTime + PointTimeInterval;
      {x}
      ep.Y := FCurVal * YMult + YAdd;
      {/x
      ep.Y := 2 * FCurVal / 1024 - FZeroValue;}
      if not FFifo.Put(ep) then
        Result := edrBufferFull;
      {/x
      FCurVal := word(b and $70) shl 3
      }
    end else begin
      {x}
      FCurVal := word(b and ValByte0Mask) shl ValByte0Shl;
      {/x
      FCurVal := FCurVal or b;

      ep.X := FCurTime / 1000;
      FCurTime := FCurTime + GHLabPointTimeInterval;
      ep.Y := 2 * FCurVal / 1024 - FZeroValue;
      if not FFifo.Put(ep) then
        Result := edrBufferFull;
      }
    end;
  end else begin
    Result := edrNotRunning;
  end;
end;

function TGHLabXDrv.ReadPoint(var APoint: TExpPoint): integer;
begin
  if FFifo.Get(APoint) then
    Result := 0
  else
    Result := -1;
end;

function ExtDevInit(var AExtDevDrv: PExtDevDrv; const ADesc: shortstring): integer;export;
var adrv: TGHLabXDrv absolute AExtDevDrv;
begin
  try
    adrv := TGHLabXDrv.Create(ADesc);
    Result := 0;
  except
    adrv := nil;
    Result := -1;
  end;
end;

function ExtDevDone(var AExtDevDrv: PExtDevDrv): integer;export;
var adrv: TGHLabXDrv absolute AExtDevDrv;
begin
  Result := -1;
  if adrv <> nil then begin
    Result := 0;
    adrv.Free;
  end;
end;

function ExtDevStart(AExtDevDrv: PExtDevDrv): integer;
var adrv: TGHLabXDrv absolute AExtDevDrv;
begin
  Result := -1;
  if adrv <> nil then begin
    Result := adrv.Start;
  end;
end;

function ExtDevStop(AExtDevDrv: PExtDevDrv): integer;
var adrv: TGHLabXDrv absolute AExtDevDrv;
begin
  Result := -1;
  if adrv <> nil then begin
    Result := adrv.Start;
  end;
end;

function ExtDevDoCharIn(AExtDevDrv: PExtDevDrv; ch:char): integer;
var
  ADrv: TGHLabXDrv absolute AExtDevDrv;
begin
  Result := ADrv.DoCharIn(ch);
end;

function ExtDevReadPoint(AExtDevDrv: PExtDevDrv; var APoint: TExpPoint): integer;
var
{  gi: TGHLabPktInfo;}
  ADrv: TGHLabXDrv absolute AExtDevDrv;
begin
  Result := ADrv.ReadPoint(APoint);
  (*
  Result := 1;
  with AExtDevDrv do begin
    {if ListRecGet(Lst, gi) then begin}
      Result := 0;
    {
  function MakeLogLine(var gi:TExtDevPacketInfo):string;
  var
    s:string;
    l:single;
    b:array[0..3]of byte absolute l;
  begin
    s := IntToStr(gi.Pkt[0]);
    MakeLogLine := s;
  end;}
  {  if LogPackets then begin
    SpectrumMemo.Lines.Add(MakeLogLine(gi));
    end;}
      for i := 0 to ExtDevPacketValueCount - 1 do begin
        CurExtDevTime := CurExtDevTime + ExtDevPointTimeInterval;
      dr.X := CurExtDevTime / 1000;


      dr.Y := 2 * (gi.Pkt[i]) / 1024 - ZeroValue;
      Data.AddPoint(dr);
      if ScrBuf[DataIndex].Points <> nil then begin
        if (dr.X >= ViewLimit.Min.X) and (dr.X <= ViewLimit.Max.X) then
        begin
          Data.ExpToScreen(dr, ScreenDisp, sr);
          ScrBuf[DataIndex].Points.AddPoint(sr.x,sr.y);
        end;
      end;
    end;
  end;
  *)
end;

end.
