unit kconcomp;
{------------------------------------------------------------------------------}
{
  KComComp - This file include Kave 2000 Control components:
    TcInverter - inverter control
    TcEncoder  - encoder control

   Author:  Vesa Lappalainen
   Date:    09.09.1996
   Changes: 02.04.1997
             + simulointi otettu pois anturista.  Simulointi tapahtuu
               nykyisin K9CIO:n kautta, joka osaa simuloida.  

}
{------------------------------------------------------------------------------}

interface

uses
  Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, kComp,KSimComp,KYasPar,KGlobal,k9cio;

type
  TNotifyInvHz = procedure(hz:double) of object;

type
  {----------------------------------------------------------------------------}
  TcInverter = class(TCounter)
  private
    FsInverter : TsInverter;
    FParams : TYasParams;
    FNotifyHz : TNotifyInvHz;
    FInError : boolean;
    FErrorClr : TColor;
    FNormalClr : TColor;
    function GetInvEnabled: boolean;               virtual;
    procedure SetInvEnabled(const Value: boolean); virtual;
    procedure SetNormalColor(const Value: TColor);
  protected
    procedure SetFreq(f:double); virtual;
//    function GetFreq:double;     virtual;
    procedure SetParams(p:TYasParams); virtual;
    function GetParams:TYasParams;     virtual;
    function GetOK:Boolean;     virtual;
    function GetInUse:Boolean;     virtual;
    procedure SetInError(b:boolean);    virtual;
  public
    ForceVisible : boolean;
    procedure SetValue(d:double);          override;
    constructor Create(AOwner:TComponent); override;
    function AccAHz:double; virtual;
    function DecAHz:double; virtual;
    function MaxHz:double; virtual;
    function MinHz:double; virtual;
    property NotifyHz : TNotifyInvHz read FNotifyHz write FNotifyHz;
    property InError : boolean read FInError write SetInError;
    property OK : boolean read GetOK;
    property InUse : boolean read GetInUse;
    property Enabled : boolean read GetInvEnabled write SetInvEnabled;
    procedure ShowColor;
  published
    property Freq:double read FValue write SetFreq;
    property sInverter:TsInverter read FsInverter write FsInverter;
    property Params : TYasParams read GetParams write SetParams;
    property ErrorClr : TColor read FErrorClr write FErrorClr;
    property NormalColor : TColor read FNormalClr write SetNormalColor;
  end;

  {----------------------------------------------------------------------------}
  TReadEncoderFn = function (LogCnt : integer) : double;

  TcEncoder = class(TCounter)
  private
//    FsEncoder : TsEncoder;
    FRatio : Double;      // Is this used??
    Fcnt   : integer;     // logical counter number
    FFysCnt   : integer;  // fysical counter (! not final card index)
    Ucnt : integer;       // logical counter at run time
    FModulus : Double;    // Modulus value
    FnReadEncoder : TReadEncoderFn; // Special read routine.
  protected
//    procedure SetCount(c:Double); virtual;
    procedure SetRatio(r:Double); virtual;
//    function GetCount:double;     virtual;
  public
    constructor Create(AOwner:TComponent); override;
    Function Speed:double;
    function GetValue:double;              override;
    procedure SetValue(d:double);          override;
    procedure Setcnt(value:integer); virtual;
    procedure SetFysCnt(value:integer); virtual;
    procedure Loaded; override;
    procedure SetReadEncoderFn(const Value: TReadEncoderFn);
  published
//    property Count:double read GetCount write SetCount;
    property Ratio:Double read FRatio write SetRatio;
    property Modulus:Double read FModulus write FModulus;
//    property sEncoder:TsEncoder read FsEncoder write FsEncoder;
    property cnt : integer read Fcnt write Setcnt;
    property FysCnt : integer read FFysCnt write SetFysCnt;
  end;

procedure Register;

implementation

{------------------------------------------------------------------------------}
{ TcInverter ==================================================================}
{------------------------------------------------------------------------------}

function TcInverter.GetOK:Boolean;
begin
  Result := false;
  if ( InError ) then exit;
  if ( not Assigned(FParams) ) then exit;
  if ( FParams.Slave <= 0 ) then exit;
  Result := true;
end;

function TcInverter.GetInUse:Boolean;
begin
  Result := false;
  if ( not Assigned(FParams) ) then exit;
  if ( FParams.Slave = NotInUseSlave ) then exit;
  Result := true;
end;

procedure TcInverter.SetInError(b:boolean);
begin
  if ( b = InError ) then exit;
//  if ( not InError ) and ( Enabled ) then FNormalClr := Color;
  FInError := b;
  ShowColor;
end;

procedure TcInverter.ShowColor;
begin
  if ( Assigned(FParams) ) then begin

    if ( Params.Slave = NotInUseSlave ) then begin
      Color := clBlack;
      Exit;
    end;
    if ( Params.Slave < 0 ) then begin
      Color := clGray;
      Exit;
    end;
  end;
  if ( InError ) then begin
    Color := ErrorClr;
    Exit;
  end;

  if ( not Enabled ) then begin
    Color := clOlive;
    Exit;
  end;

  Color := FNormalClr;
end;

procedure TcInverter.SetNormalColor(const Value: TColor);
begin
  FNormalClr := Value;
  ShowColor;
end;

function TcInverter.GetInvEnabled: boolean;
begin
  Result := true;
  if ( Assigned(FParams) ) then
    Result := Params.Enabled;
end;

procedure TcInverter.SetInvEnabled(const Value: boolean);
begin
  if ( Assigned(FParams) ) then
    Params.Enabled := Value;
  ShowColor;
end;

function TcInverter.AccAHz:double;
begin
  Result := 1;
  if ( Assigned(FParams) ) then
    Result := FParams.AccAHz;
end;

{------------------------------------------------------------------------------}
function TcInverter.DecAHz:double;
begin
  Result := 1;
  if ( Assigned(FParams) ) then
    Result := FParams.DecAHz;
end;

{------------------------------------------------------------------------------}
function TcInverter.MaxHz:double;
begin
  Result := 1;
  if ( Assigned(FParams) ) then
    Result := FParams.ReadMaxHz;
end;

{------------------------------------------------------------------------------}
function TcInverter.MinHz:double;
begin
  Result := 1;
  if ( Assigned(FParams) ) then
    Result := FParams.ReadMinHz;
end;

{------------------------------------------------------------------------------}
procedure TcInverter.SetParams(p:TYasParams);
begin
  FParams := p;
end;

{------------------------------------------------------------------------------}
function TcInverter.GetParams:TYasParams;
begin
  Result := FParams;
end;

{------------------------------------------------------------------------------}
procedure TcInverter.SetValue(d: double);
begin
  if ( InError ) then exit;
  inherited SetValue(d);
  if ( simulation and Assigned(FsInverter) ) then FsInverter.Freq := d;
  if ( not Simulation ) and Assigned(FParams) then
    FParams.WriteRunHz(d);
  if ( assigned(FNotifyHz) ) then FNotifyHz(d);
end;

{------------------------------------------------------------------------------}
procedure TcInverter.SetFreq(f:double);
begin
  SetValue(f);
end;

{------------------------------------------------------------------------------}
{
function TcInverter.GetFreq:double;
begin
  Result := Value;
end;
}

{------------------------------------------------------------------------------}
constructor TcInverter.Create(AOwner:TComponent);
begin
  ForceVisible := false;
  FParams := NIL;
  FsInverter := NIL;
  FNotifyHz := NIL;
  FErrorClr := clRed;
  FNormalClr := clYellow;
  FInError := false;
  inherited Create(AOwner);
  FNormalClr := Color;
end;

{------------------------------------------------------------------------------}
{ TcEncoder ===================================================================}
{------------------------------------------------------------------------------}

{------------------------------------------------------------------------------}
constructor TcEncoder.Create(AOwner:TComponent);
begin
  inherited Create(AOwner);
  FRatio := 1;
  Fcnt := 0;
  UCnt := 0;
  FFysCnt := -1;
  FModulus := 0;
  Ini.AutoSave := false;
//  FsEncoder := NIL;
end;

{------------------------------------------------------------------------------}
procedure TcEncoder.SetRatio(r:Double);
begin
  FRatio := r;
  if ( r = 0 ) then FRatio := 1;
end;

(*
{------------------------------------------------------------------------------}
procedure TcEncoder.SetCount(c:Double);
begin
  Value := c;
end;

{------------------------------------------------------------------------------}
function TcEncoder.GetCount:double;
begin
  Result := Value;
end;
*)

{------------------------------------------------------------------------------}
function TcEncoder.Speed:double;
begin
//  Result := 0;
  if ( ( Ucnt > 0 ) ) then Result := ReadVCounterSpeed(cnt)
//  if ( ( not simulation ) and ( cnt > 0 ) ) then Result := ReadCntSpeed(cnt)
  else Result := 0;  // Korjaa tämä simulointiin
end;

procedure Register;
begin
  RegisterComponents('Kave2000', [TcInverter,TcEncoder]);
end;


//-----------------------------------------------------------------------------
procedure TcEncoder.SetValue(d:double); //           override;
begin
  if ( Ucnt > 0 ) then begin SetVCounter(cnt,d); end;
  inherited SetValue(d);
//  if ( ( not simulation ) and ( cnt > 0 ) ) then begin SetCounter(cnt,c); value := c; end
//  else if ( Assigned(sEncoder) ) then sEncoder.Count := c/Ratio;
end;


//-----------------------------------------------------------------------------
function TcEncoder.GetValue:double; //               override;
begin
  if ( Ucnt <= 0 ) then begin Result := inherited GetValue; exit; end;
  if Assigned(FnReadEncoder) then begin
    Result := FnReadEncoder(Ucnt);
  end else begin
    Result := ReadVCounter(cnt);
    if FModulus<>0 then begin
      Result:=Frac(Result/FModulus)*FModulus;
      if Result<0 then Result:=FModulus+Result;
    end
  end;
//  if ( ( not simulation ) and ( cnt > 0 ) ) then Result := ReadCounter(cnt)
//  else if ( Assigned(FsEncoder) ) then Result := FsEncoder.Count*Ratio;
  inherited SetValueNoSave(Result);
end;


//-----------------------------------------------------------------------------
procedure TcEncoder.Setcnt(value:integer); //  virtual;
begin
  Fcnt := value;
  if ( not (csDesigning in ComponentState) ) then Ucnt := FCnt;
end;

//-----------------------------------------------------------------------------
procedure TcEncoder.SetFysCnt(value:integer); //  virtual;
begin
  FFysCnt := value;
  if ( not (csDesigning in ComponentState) ) then begin
    JoinVCounter(FCnt,FFysCnt);
  end;
end;


//-----------------------------------------------------------------------------
procedure TcEncoder.Loaded; // override;
begin
  if ( not (csDesigning in ComponentState) ) then begin
    Ucnt := FCnt;
    JoinVCounter(FCnt,FFysCnt);
  end;
  inherited;
end;

procedure TcEncoder.SetReadEncoderFn(const Value: TReadEncoderFn);
begin
  FnReadEncoder := Value;
end;

end.

