(*
*******************************************************************************
*         Copyright (C) SofCon 2003 All Rights Reserved                       *
*******************************************************************************
*
*    project:     vizualizace
*
*    title:       Param.pas
*
*******************************************************************************
*
*    description: priklad podpory s prenosu parametru a zasilani prikazu
*
*    version:     1.05
*    language:    Borland Pascal
*
*    author:      Hvozdovic
*    history:     date      sign   remark
*                 8.02      hv     zacatek vyvoje
*                11.02      hv     prvni release
*                11.02      hv     zruseni odkazu na ChnPrt, ChnVirt,
*                                  ChnSofs2, ChnSofT
*		 12.02	    hv	   uprava zapisu a cteni parametru
*					(zruseni MOVE, protoze se obchazely
*					 typove kontroly - tezko odhalitelne
*					 chyby)
*                03.03      bi     doplnena obsluha systemoveho parametru
*				   LA_firmwareAppVer, dalsich on-line parametru
*                 9.03      hv     knihovna pouziva rozsirenou
*                                       standardni knihovnu Crc16
*                                  Pozn. Drivejsi verze pouzivala knihovnu ExCrc16
*				   Zruseno konstanta cName
*				   Pridana konstanta cVerNo a cVer upravena
*					do standardizovaneho formatu
*****************************************************************************
*)
{$I sets.inc}

unit Param;
interface
uses
   Objects            { objekty }
  ,Xtking_1           { definice typu a konstant pro praci s vizualizaci }
  ,WTVirt             { virtualni predek vsech vizualizacnich objektu }
  ,WTErr              { definice chybovych kodu funkcnich objektu vizualizace }
  ,Kernel             { ReTOS }
  ,NumToStr           { prace s retezci }
  ,WTPar              { objekt s implementaci podpory prenosu parametru }
  ,XCrExam1           { definice konstant pro prenos parametru -
                        na zaklade techto definic se generuje CSV soubor
                        pro vizualizaci }
  ;

type
  { objekt pracujici s uzivatelskymi daty }
  PParam = ^TParam;
  TParam = object(TWinTickParam)
    constructor Init;
    destructor Done; virtual;

    procedure SetResultCode(RetCode:Word; LA:Word); virtual;

    function fnGetParamVal(var LA:Word; var Data):Word; virtual;
    function fnPutParamVal(var LA:Word; var Data):Word; virtual;
    { obsluha blokovych prenosu se provadi v predku prenosu parametru }
    function fnGetParamSize(LA:Word):Word; virtual;
    { cast online parametru na urovni firmware jsou obslouzeny v predku.
      Nektere z techto parametru se ale musi obslouzit az ve vlastni
      aplikaci. }
    function  fnGetFirmwareParamVal(var LA:Word; var Data):Word; virtual;
    function  fnPutFirmwareParamVal(var LA:Word; var Data):Word; virtual;
  end;

  { struktura, ve ktere jsou ulozena data prenasena smerem do vizualizace
    a z vizualizace do programu. Vlastni popis prenasenych dat je
    v soubor xCrExam1. }
  TValue = record
    byte1 : Byte;
    byte2 : Byte;
    enum1 : byte;
    enum2 : byte;
    word  : Word;
    word1 : word;
    integer1 : LongInt;
    long  : LongInt;
    longword : LongInt;
    real  : real;
    r2,r3 : real;
    s : string[10];
    sw1,sw2 : word;
    t1,t2:tutemperature;
  end;


{ procedura pro zobrazeni stavu promennych - zobrazi se bud stiskem
  klavesy "1" nebo stiskem tlacitka "Zobraz parametry" ve vizualizacnim SW }
procedure ShowState;


implementation
uses
   Strings
  ,xDesc
  ,AppDesc
  ,Crc16
  ;

var
  { definice struktury s uzivatelskymi daty }
  value:TValue;

const
  { uzivatelske chybove navratove kody }
  rc_NotWritten = 21;
  str_NotWritten = 'Variable could not be written';


constructor TParam.Init;
begin
  inherited Init;

  { inicializace uzivatelskych dat }
  FillChar(value, sizeof(value), 0);
end;

destructor TParam.Done;
begin
  inherited Done;
end;

function TParam.fnGetParamVal(var LA:Word; var Data):Word;
var
  fLock:Boolean;
  theCrc:tCrc16;
begin
 { synchronizace promennych - zamknuti jadra proti prepnuti
   procesu.
   Tato synchronizace je dostatecna pokud k promennym pristupuji
   ruzne procesy. V pripade pristupu k promennym z prerusovaci
   obsluhy by zde musela byt pouzito zakazani preruseni (pushf cli) }
 fLock:=ExLockKernel;
  { nastaveni datoveho bufferu dle dotazovane promenne prostrednictvim LA.
    Definice LA je uvedena v souboru xCrExam1 }
  fnGetParamVal:=rc_Ok;
  case LA of
    LA_VersionGlb_Ver: treal(data) := 1.01;
    LA_DemoByte1     : Byte(Data):=value.Byte1;
    LA_DemoByte2     : Byte(Data):=value.Byte2;
    LA_DemoEnum1     : Byte(Data):=0;
    LA_DemoEnum2     : Byte(Data):=0;
    LA_DemoWord1     : Word(Data):=value.Word;
    LA_DemoSmallInt1 : Word(Data):=value.Word1;
    LA_DemoInteger1  : LongInt(data):=value.integer1;
    LA_DemoLongInt1  : LongInt(Data):=value.Long;
    LA_DemoLongWord1 : Longint(data):=value.longword;
    LA_DemoRealp1    : Real(Data):=value.real;
    LA_DemoRealp2    : Real(Data):=value.r2;
    LA_DemoRealp3    : Real(Data):=value.r3;
    LA_DemoString1   : string(data):=value.s;
    LA_DemoSpecWord1 : Word(data):=value.sw1;
    LA_DemoSpecWord2 : Word(data):=value.sw2;
    LA_CFTemperature1: begin
                         value.T1.utemperunit := utunit_degreecelsius;
                         tutemperature(data) := value.T1;
                       end;
    LA_CFTemperature2: begin
                         value.T2.utemperunit := utunit_degreecelsius;
                         tutemperature(data) := value.T2;
                       end;

  else
    fnGetParamVal:=rc_NotImplemented;
  end;

 { synchronizace promennych - odemknuti jadra, viz. vyse }
 if not fLock then UnLockKernel;
end;

function TParam.fnPutParamVal(var LA:Word; var Data):Word;
var
  fLock:Boolean;
  theCrc:tCrc16;
begin
 { synchronizace promennych - zamknuti jadra proti prepnuti
   procesu.
   Tato synchronizace je dostatecna pokud k promennym pristupuji
   ruzne procesy. V pripade pristupu k promennym z prerusovaci
   obsluhy by zde musela byt pouzito zakazani preruseni (pushf cli) }
 fLock:=ExLockKernel;
  { nastaveni promenne urcene prostrednictvim LA na hodnotu v datovem
    bufferu
    Definice LA je uvedena v souboru xCrExam1 }
  fnPutParamVal:=rc_Ok;
  case LA of
    LA_DemoByte1: value.Byte1:=Byte(Data);
    LA_DemoByte2: value.Byte2:=Byte(Data);
    LA_DemoWord1: value.Word:=Word(Data);
    LA_DemoSmallInt1:
      begin
        { pri nastavovani pripadne cteni lze provadet konverze
          nebo kontroly.
          V tomto pripade se kontroluje nastaveni promenne (value.word)
          a pokud je splnena podminka, je prenesena hodnota
          nastavena do promenne }
        if value.word > 5 then
          fnPutParamVal:=rc_NotWritten
        else
          value.word1:=Word(Data);
      end;
    LA_DemoInteger1: value.integer1 := longint(data);
    LA_DemoLongInt1: value.Long:=LongInt(Data);
    LA_DemoLongWord1: value.longword := longint(data);
    LA_DemoRealp1: value.real:=Real(Data);
    LA_DemoRealp2: value.r2 :=Real(data);
    LA_DemoRealp3: value.r3 :=Real(data);
    LA_DemoString1: Value.S := string(data);
    LA_DemoSpecWord2: value.sw2 := word(data);
    LA_CFTemperature1: value.T1 := tutemperature(data);
    LA_CFTemperature2: value.T2 := tutemperature(data);

  { prikaz }
    LA_DemoEnum1: ShowState;
    LA_DemoEnum2: RunError(254);
    LA_DemoSpecWord1:
      begin
        gpLdrDesc^.bParForLdr:=1;
        gpLdrDesc^.wCrc:=theCrc.CalculateCrc(gpLdrDesc, cLdrDescCrcSize, cLdrResidue);
       {$ifdef VerMC}
        asm cli end;
        repeat until false;
       {$else}
        halt;
       {$endif}
      end;

  else
    fnPutParamVal:=rc_NotImplemented;
  end;

 { synchronizace promennych - odemknuti jadra, viz. vyse }
 if not fLock then UnLockKernel;
end;

function TParam.fnGetParamSize(LA:Word):Word;
begin
(*
  { pri malem mnozstvi parametru lze pouzit CASE }
  fnGetParamSize:=0;
  case LA of
    LA_DemoByte1,
    LA_DemoByte2: fnGetParamSize:=sizeof(Byte);

    LA_DemoWord1,
    LA_DemoSmallInt1:
                  fnGetParamSize:=sizeof(Word);

    LA_DemoLongInt1: fnGetParamSize:=sizeof(LongInt);
    LA_DemoRealp1: fnGetParamSize:=sizeof(Real);
  end;
*)

  { Pri velkem mnozstvi parametru doporucujeme pouzivat tabulku.
    Tabulka se v tomto pripade nastavuje v souboru XCrExam1
    a vytvari se manualne pri definici jednotlivych parametru. }
  fnGetParamSize:=GetOnLineParSize(LA);
end;

function TParam.fnGetFirmwareParamVal(var LA:Word; var Data):Word;
var
  wRet:Word;
begin
  wRet:=inherited fnGetFirmwareParamVal(LA, Data);

  if wRet = rc_NotImplemented then
  begin
    case LA of
      LA_RstStruct: { cteni ErrDescArray }
        begin
          with tRstStruct(Addr(Data)^), gpAppRstDesc^ do
          begin
            Verse:=wAppVer;
            RstCt:=wRunErrCnt;
            ARst:=bIxWrittenAt;
            Rst:=ErrDescArray;
          end;
          wRet:=rc_Ok;
        end;
      LA_firmwareAppVer: begin
                           tappverstr(addr(data)^) := 'Example1 02.01';
                           wRet := rc_OK;
                         end;
    end;
  end;
  fnGetFirmwareParamVal:=wRet;
end;


function TParam.fnPutFirmwareParamVal(var LA:Word; var Data):Word;
var
  wRet:Word;
begin
  wRet:=inherited fnPutFirmwareParamVal(LA, Data);

  if wRet = rc_NotImplemented then
  begin
    case LA of
      LA_ClrRstStruct: { inicializace struktur LdrDesc a AppRstDesc }
        begin
          InitLdrDesc(gpLdrDesc);
          InitAppRstDesc(gpAppRstDesc);
          wRet:=rc_Ok;
        end;
    end;
  end;
  fnPutFirmwareParamVal:=wRet;
end;

procedure TParam.SetResultCode(RetCode:Word; LA:Word);
begin
  { obsluha uzivatelskych chybovych kodu }
  if RetCode = rc_NotWritten then
  begin
    m_pSMess^.Cmd:=gcmd_Result;
    with tgcmd_Result(Addr(m_pSMess^.Rec)^) do
    begin
      ResultCode:=retCode;
      StrPCopy(ResultSz, 'LA='+WordStrDec(LA,1)+' '+str_NotWritten);
    end;
  end
  else
    inherited SetResultCode(RetCode,LA);
end;


procedure ShowState;
var
  fLock:Boolean;
begin
  { synchronizace promennych - zamknuti jadra proti prepnuti
    procesu.
    Tato synchronizace je dostatecna pokud k promennym pristupuji
    ruzne procesy. V pripade pristupu k promennym z prerusovaci
    obsluhy by zde musela byt pouzito zakazani preruseni (pushf cli) }
  fLock:=ExLockKernel;
  { zobrazeni uzivatelskych dat}
   with value do
   begin
     writeln('Byte1: ', ByteStrDec(byte1,3));
     writeln('Byte2: ', ByteStrHex(byte2));
     writeln('Word: ', WordStrDec(word,5));
     writeln('Word1: ', WordStrDec(word1,5));
     writeln('Longint: ', long:10);
     writeln('Real: ', real:3:4);
   end;
  { synchronizace promennych - odemknuti jadra, viz. vyse }
  if not fLock then UnLockKernel;
end;

end.
