unit GHLabu;
interface
uses
  UlanType, GHLabType;
  
{ The following methods will be called by Chromulan, either upon program startup or 
  during acquistion (for the channel, which have assigned this device). }

{The first method to be called - load, initialize the driver, get handle of the driver - AExtDevDrv.
ADesc as a string that can be assigned in Chromulan in browser of devices. This device will appear
in the list, if its DLL is found in dev subdirectory of Chromulan installation directory
(and if the DLL has all the following methods exported). }
function ExtDevInit(var AExtDevDrv: PExtDevDrv; const ADesc: shortstring): integer; export;

{Called when acquisition started.}
function ExtDevStart(AExtDevDrv: PExtDevDrv): integer; export;

{Called when acquisition stopped.}
function ExtDevStop(AExtDevDrv: PExtDevDrv): integer; export;

{Called during acquisition when a character ch comes through the device's port 
(i.e., all characters are read by Chromulan and given (forwarded) to this device 
driver using this method.)}
function ExtDevDoCharIn(AExtDevDrv: PExtDevDrv; ch:char): integer; export;

{Called by Chromulan to retrieve data point (assembled by the driver from characters obtained
by ExtDevDoCharIn methods), should return 0 if some point available and assigned to APoint,
otherwise return -1. }
function ExtDevReadPoint(AExtDevDrv: PExtDevDrv; var APoint: TExpPoint): integer; export;

{Deinitialize, unload the driver.}
function ExtDevDone(var AExtDevDrv: PExtDevDrv): integer; export;

implementation
uses
  fifou, timer, inifiles;
const
  GHLabBufSlotCount: integer = 1024;
  GHLabPointTimeInterval: single = 31.25;{ms}

type
  TGHLabDrv = class(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;
    FZeroValue: single;
    FRunning: boolean;
  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;
  end;


constructor TGHLabDrv.Create(ADesc: shortstring);
begin
  inherited Create;
  FDesc := ADesc;
  FFifo := TFifo.Create(sizeof(TExpPoint), GHLabBufSlotCount);
end;

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

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

destructor TGHLabDrv.Destroy;
begin
  FFifo.Free;
  inherited Destroy;
end;

function TGHLabDrv.DoCharIn(ch:char): integer;
var
  b: byte absolute ch;
  ep: TExpPoint;
begin
  if FRunning then begin
    Result := 0;
    if (b and  $80) <> 0 then begin
      FCurVal := word(b and $70) shl 3
    end else begin
      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 TGHLabDrv.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: TGHLabDrv absolute AExtDevDrv;
begin
  try
    adrv := TGHLabDrv.Create(ADesc);
    Result := 0;
  except
    adrv := nil;
    Result := -1;
  end;
end;

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

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

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

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

function ExtDevReadPoint(AExtDevDrv: PExtDevDrv; var APoint: TExpPoint): integer;
var
{  gi: TGHLabPktInfo;}
  ADrv: TGHLabDrv 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.