(*
*******************************************************************************
*         Copyright (C) SofCon 2002 All Rights Reserved                       *
*******************************************************************************
*
*    project:     Ukazka vizualizace pomoci TheKing
*
*    title:       KitKing.pas
*
*******************************************************************************
*
*    description: hlavni telo prikladu vizualizace pomoci TheKing
*
*    version:     2.02 (viz konstanta cAplicationVer v unite AppDesc)
*    language:    Borland Pascal 7.0
*
*    author:      Hvozdovic
*    history:     date      sign   remark
*                 8.02      hv     zacatek vyvoje
*                11.02      hv     prvni release
*		 11.02      hv	   oprava inicializace objektu (Init)
*    	  	 		   upravy volani objektu TWinCom
*				   doplnen komunikacni kanal UDP
*                03.03      bi     pridan konfig. retezec pro komunikaci s
*                                  KITem pres COM2 na desce IOPCOM
*****************************************************************************
*)
{$I sets.inc}


program KitKing;
uses
  _1stUnit,            { jednotka zajistujici podporu DPMI a zachyceni chyby }
  LibVer,              { definice formatu verze }
 {$ifdef Deb_crt}
  Crt,                 { podpora vystupu }
 {$endif}
 {$ifdef V40}
  ChnV40_,	       { objekt pracujici s komunikacnim portem na procesoru V40 }
 {$endif}
 {$ifdef COM}
  ChnCom,	       { objekt pracujici se standardnim komunikacnim portem }
 {$endif}
 {$ifdef UDP}
  UDPPrt,              { komunikacni protokol PRT prenaseny pomoci UDP }
  CoUDP,               { objekt prenasejici data pomoci protokolu UDP }
  {$ifdef Deb}
   CoBase,              { pro ladici ucely }
  {$endif}
 {$else}
  ChnPrt,              { komunikacni protokol Prt }
 {$endif}
  ChnVirt,             { virtualni kanal }
  ChnSofs2,            { prenos dat pomoci protokolu SofCon }
  WinCom,              { komunikacni objekt spravujici objekty vizualizace }
 {$ifdef FILE1}
  File1,               { priklad s implementaci dvou malych souboru }
 {$endif}
 {$ifdef FILE2}
  File2,               { priklad s implementaci dvou velkych souboru }
 {$endif}
 {$ifdef LOADER}
  Loader,              { priklad s aplikaci LOADER }
 {$endif}
 {$ifdef PARAM}
  Param,               { priklad s prenosem jednotlivych parametru,
                         blokovym prenosem parametru a parametru jako prikazu }
 {$endif}
 {$ifdef ARCHIVE1}
  Archive1,            { priklad s dvemi archivy bez podpory grafu }
 {$endif}
 {$ifdef ARCHIVE2}
  Archive2,            { priklad s jednim archivem podporujicim graf }
 {$endif}
  uxDesc,              { nastaveni sdilenych promennych s LOADER }
  AppDesc,             { jednotka definujici kompletni rozlozeni pameti
                         v aplikaci LOADER, pouziva xDesc
                         Dale v teto jednotce muzou byt aplikacne zavisle
                         struktury a konstanty }
  Kernel,              { jadro os ReTOS }
  NumToStr             { prace s retezci }
  ;



const
 {$ifNdef UDP}
  cCommHead   = 'NAM=SOFS2 LRB=2500 LSB=3000 NAM=PRT LSB=2500 DNOD=$10 NOD=';
 {$else}
  cCommHead   = 'NAM=SOFS2 LRB=2500 LSB=3000 NAM=UDPPRT LRB=2500 LSB=2500 DNOD=$10 NOD=';
 {$endif}
 {$ifdef COM}
  {$ifdef VerPC}
    cCommParam = 'NAM=COM COM=1 IRQ=4 BD=38400 BIT=8 PAR=N STO=2 LRB=2500 ';
{    cCommParam = 'NAM=COM COM=2 IRQ=3 BD=38400 BIT=8 PAR=N STO=2 LRB=2500 ';}
  {$else}
    {KIT IOPCOM - COM2}
    {cCommParam = 'NAM=COM ADD=$2320 IRQ=4 BD=38400 BIT=8 PAR=N STO=2 LRB=2500';}
    {KIT386EXR  - COM1}
    cCommParam = 'NAM=COM COM=1 IRQ=4 BD=38400 BIT=8 PAR=N STO=2 LRB=2500';
  {$endif}
 {$endif}
 {$ifdef V40}
   cCommParam = 'NAM=V40_ BD=38400 BIT=8 PAR=N STO=2 LRB=2500';
 {$endif}

  key:Char = #0;      { pomocna klavesa v hlavnim procesu pro ukonceni aplikace }

var
  TheWinCom:TWinCom;  { komunikacni objekt spravujici jednotlive objekty
                        vizualizace - soubory, archivy, prenos parametru
                        a aplikaci LOADER }
 {$ifdef FILE1}
  pTheFile1:PFile1;   { objekt s implementaci dvou malych souboru }
 {$endif}
 {$ifdef FILE2}
  pTheFile2:PFile2;   { objekt s implementaci dvou velkych souboru }
 {$endif}
 {$ifdef LOADER}
  pTheLoader:PLoader; { objekt s implementaci podpory pro aplikaci LOADER }
 {$endif}
 {$ifdef PARAM}
  pTheParam:PParam;   { objekt s implementaci prenosu jednotlivych parametru,
                        blokovych prenosu parametru a parametru jako prikazu }
 {$endif}
 {$ifdef ARCHIVE1}
  pTheArchive1:PArchive1;  { objekt s implementaci dvou archivu bez podpory grafu }
 {$endif}
 {$ifdef ARCHIVE2}
  pTheArchive2:PArchive2;  { objekt s implementaci jednoho archivu podporujicim grafy }
 {$endif}

const
  Write_Name   = 'Write';
  cNode : Byte = 1;


{ Procedura implementujici proces sa zapisy dat do archivu }
procedure ExecWriteToArchive; far;
const
  Write_Stack = 8000;
  Write_SPrio = 90;
  Write_DPrio = 254;

begin
{$ifdef Deb_crt}
  writeln('Spusteni zapisovaciho procesu.', Write_Name);
{$endif}

  { ++++++++++++++++ }
  { spusteni procesu }
  { ++++++++++++++++ }
  Start(Write_Name, Write_Stack, Write_SPrio, Write_DPrio); Exit;

 {$ifdef ARCHIVE1}
  WriteToArchive;
 {$endif}
 {$ifdef ARCHIVE2}
  WriteToArchive;
 {$endif}

{$ifdef Deb_crt}
  writeln('Ukonceni zapisovaciho procesu.', Write_Name);
{$endif}
  Terminate;
end;

{ zruseni procesu zapisujici do archivu a ve verzi
  pro PC se uvolni pamet pouzivana archivy }
procedure DestructWriteToArchive; far;
begin
 {$ifdef ARCHIVE1}
  DestructArchive;
 {$endif}
 {$ifdef ARCHIVE2}
  DestructArchive;
 {$endif}
  if not TestKernel then exit;
  Abort(Write_Name);
end;

procedure EatMemory( MemRest:LongInt );
const
  BlkSize:LongInt = $E000;
var
  P : Pointer;
begin
  while MemRest<MemAvail do
  begin
    GetMem( P, BlkSize );
    if P=nil then RunError(255);
    if MemAvail < (MemRest + BlkSize) then BlkSize:=MemAvail-MemRest;
  end;
end;


begin
 {$ifdef VerPC}
{  EatMemory(47000);}
  EatMemory(60000);
  HeapSize:=MemAvail;
 {$endif}
 {$ifdef UDP}
  {$ifdef DEBUG_ALLOCATIONS}
   writeln('MemAvail for app:=', MemAvail,
          '; (CoBase:',XX_ReqMem,',',XX_PktMem,')');
  {$else}
   writeln('MemAvail for app:=', MemAvail);
  {$endif}
 {$else}
  writeln('MemAvail for app:=', MemAvail);
 {$endif}
  delay(1000);

  AdaptToMyApp;

  { nastaveni identifikacniho retezce aplikace }
{$ifdef ARCHIVE1}
  strAppName:='Archive1 v' + VerNoToStr(cAplicationVer);
{$else}
 {$ifdef ARCHIVE2}
  strAppName:='Archive2 v' + VerNoToStr(cAplicationVer);
 {$else}
  strAppName:='KitKing v'  + VerNoToStr(cAplicationVer);
 {$endif}
{$endif}

  { inicializace struktur popisujici pamet }
  fnAppInit;

 {$ifdef Deb_crt}
  clrscr;
  writeln('Spusteni a inicializace jadra');
 {$endif}
  { spusteni a inicializace jadra ReTOS - vytvoreni hlavniho procesu }
  StartMain(200, 254);
  InitInterruptStack(1,254);
  StartTimeSlicing(8);

  { inicializace komunikacniho kanalu }
  TheWinCom.Init;

  { vytvoreni retezce komunikacnich objektu odvozenych od ChnVirt
    V teto dobe jeste neexistuji objekty odvozene od CoBase }
 {$ifNdef UDP}
   if TheWinCom.CreateChn(cCommHead+ByteStrHex(cNode)+' '+cCommParam)<>Res_Ok then
 {$else}
  if TheWinCom.CreateChn(cCommHead+ByteStrHex(cNode))<>Res_Ok then
 {$endif}
  begin
   {$ifdef Deb_crt}
    writeln('Nepodarilo se vytvorit komunikacni kanal: ', TheWinCom.m_ChnDesc.pChannel^.ChGetParam(''));
   {$endif}
    RunError(255);
  end;

  { vytvoreni komunikacniho retezce podle predanych a
    defaultnich parametru }
 {$ifdef VerMC}
  {$ifdef UDP}
   with pUdpPRT(TheWinCom.m_ChnDesc.pChannel^.Ch_Chn)^ do
   begin
     { prenastaveni defaultnich parametru kanalu - NIC
       <NETWORK INTERFACE CARD> }
     CH_NicName  :='ETH01';
    {$ifdef MCP}
     CH_NicParam :='IOBASE=$2300';
    {$else}
     CH_NicParam :='IOBASE=$300';
    {$endif}

     { prenastaveni defaultnich parametru kanalu - IP
       <INTERNET PROTOKOL> }
     CH_IPParam  :='IPADDR="192.168.1.200" NETMASK="255.255.255.0"';

     { prenastaveni defaultnich parametru kanalu - UDP
       <USER DATAGRAM PROTOCOL> }
     CH_UDPParam :='LPORT=5000';
   end;
   { prenastaveni defaultnich parametru kanalu - UDPPRT }
   TheWinCom.m_ChnDesc.pChannel^.ChSetParam('NAM=SOFS2 DF2=0 NAM=UDPPRT NOD=1');
    { zjisteni zpusobu komunikace }
  {$else}
   { prenastaveni defaultnich parametru kanalu - PRT }
   TheWinCom.m_ChnDesc.pChannel^.ChSetParam('NAM=SOFS2 DF2=0 NAM=PRT NOD=1');
  {$endif}
 {$else}
  {$ifdef UDP}
   with pUdpPRT(TheWinCom.m_ChnDesc.pChannel^.Ch_Chn)^ do
   begin
     { prenastaveni defaultnich parametru kanalu - NIC
       <NETWORK INTERFACE CARD> }
     CH_NicName  :='ETH01';
    {$ifdef MCP}
     CH_NicParam :='IOBASE=$2300';
    {$else}
     CH_NicParam :='IOBASE=$300';
    {$endif}

     { prenastaveni defaultnich parametru kanalu - IP
       <INTERNET PROTOKOL> }
     CH_IPParam  :='IPADDR="192.168.1.201" NETMASK="255.255.255.0"';

     { prenastaveni defaultnich parametru kanalu - UDP
       <USER DATAGRAM PROTOCOL> }
     CH_UDPParam :='LPORT=5000';
   end;
   { prenastaveni defaultnich parametru kanalu - UDPPRT }
   TheWinCom.m_ChnDesc.pChannel^.ChSetParam('NAM=SOFS2 DF2=0 NAM=UDPPRT NOD=2');
  {$else}
   { prenastaveni defaultnich parametru kanalu - PRT }
   TheWinCom.m_ChnDesc.pChannel^.ChSetParam('NAM=SOFS2 DF2=0 NAM=PRT NOD=1');
  {$endif}
 {$endif}

  { otevreni kom. kanalu }
 {$ifNdef UDP}
  if TheWinCom.Open<>Res_Ok then
 {$else}
  if TheWinCom.Open<>Res_Ok then
 {$endif}
  begin
   {$ifdef Deb_crt}
    writeln('Nepodarilo se otevrit komunikacni kanal: ', TheWinCom.m_ChnDesc.pChannel^.ChGetParam(''));
   {$endif}
    RunError(255);
  end;

  writeln('Parametry <ChnVirt>: ', TheWinCom.m_ChnDesc.pChannel^.ChGetParam(''));
 {$ifdef UDP}
  { zobrazeni parametru komunikacniho kanalu }
  with pUdpPRT(TheWinCom.m_ChnDesc.pChannel^.Ch_Chn)^ do
  begin
    writeln('Parametry NIC:    ', ChGetParam('NIC'));
    writeln('Parametry IP:     ', ChGetParam('IP'));
    writeln('Parametry UDP:    ', ChGetParam('UDP'));
  end;
 {$endif}

 {$ifdef UDP}
  { prenastaveni parametru otevreneho kanalu - UDPPRT }
  TheWinCom.m_ChnDesc.pChannel^.ChGetParam('NAM=UDPPRT NOD='+ByteStrHex(2));
  with pUdpPRT(TheWinCom.m_ChnDesc.pChannel^.Ch_Chn)^ do
  begin
    { POZOR: ne vsechny parametry lze menit za chodu -> CoBind }
    ChSetParam('NAM=NIC MONCSN=1');
    writeln('--------- NIC: ', ChGetParam('NIC'));

    { POZOR: ne vsechny parametry lze menit za chodu -> CoBind }
    ChSetParam('NAM=IP TTL=64');
    writeln('--------- IP: ', ChGetParam('IP'));

    { POZOR: ne vsechny parametry lze menit za chodu -> CoBind }
    ChSetParam('NAM=UDP LPORT=5000');
    writeln('--------- UDP: ', ChGetParam('UDP'));
  end;
 {$endif}

  { inicializace objektu vizualizace a jeho pridani do komunikacniho objektu }
 {$ifdef FILE1}
  pTheFile1:=new(PFile1, Init);
  if pTheFile1=nil then RunError(255);
  if not TheWinCom.Register(pTheFile1) then
  begin
   {$ifdef Deb_crt}
    Writeln('Objekt vizualizace nelze pridat do smycky zpracovani');
   {$endif}
    RunError(255);
  end;
 {$endif}
 {$ifdef FILE2}
  pTheFile2:=new(PFile2, Init);
  if pTheFile2=nil then RunError(255);
  if not TheWinCom.Register(pTheFile2) then
  begin
   {$ifdef Deb_crt}
    Writeln('Objekt vizualizace nelze pridat do smycky zpracovani');
   {$endif}
    RunError(255);
  end;
 {$endif}
 {$ifdef LOADER}
  pTheLoader:=new(PLoader, Init);
  if pTheLoader=nil then RunError(255);
  if not TheWinCom.Register(pTheLoader) then
  begin
   {$ifdef Deb_crt}
    Writeln('Objekt vizualizace nelze pridat do smycky zpracovani');
   {$endif}
    RunError(255);
  end;
 {$endif}
 {$ifdef PARAM}
  pTheParam:=new(PParam, Init);
  if pTheParam=nil then RunError(255);
  if not TheWinCom.Register(pTheParam) then
  begin
   {$ifdef Deb_crt}
    Writeln('Objekt vizualizace nelze pridat do smycky zpracovani');
   {$endif}
    RunError(255);
  end;
 {$endif}
 {$ifdef ARCHIVE1}
  pTheArchive1:=new(PArchive1, Init);
  if pTheArchive1=nil then RunError(255);
  if not TheWinCom.Register(pTheArchive1) then
  begin
   {$ifdef Deb_crt}
    Writeln('Objekt vizualizace nelze pridat do smycky zpracovani');
   {$endif}
    RunError(255);
  end;
 {$endif}
 {$ifdef ARCHIVE2}
  pTheArchive2:=new(PArchive2, Init);
  if pTheArchive2=nil then RunError(255);
  if not TheWinCom.Register(pTheArchive2) then
  begin
   {$ifdef Deb_crt}
    Writeln('Objekt vizualizace nelze pridat do smycky zpracovani');
   {$endif}
    RunError(255);
  end;
 {$endif}

  { spusteni procesu zapisujiciho do archivu }
  ExecWriteToArchive;

  { spusteni komunikacniho procesu }
  if not TheWinCom.CreateProcess then
  begin
   {$ifdef Deb_crt}
    Writeln('Komunikacni objekt nemuze byt vytvoren');
   {$endif}
    RunError(255);
  end;

  { snizeni priority hlavniho procesu }
  SetPriority(50, 254);

 {$ifNdef VerMC}
  repeat
   {$ifdef Deb_crt}
    if KeyPressed then
    begin
      key:=ReadKey;

      case key of
      '1': ShowState;
      '2': delay(1);
      end;
      writeln('Pro ukonceni programu - (x/X)');
    end;
   {$endif}
    Wait(1);
  until UpCase(key)='X';
 {$else}
  { ukonceni se provede bud RESET nebo pomoci prikazu LOADER }
  repeat
  until false;
 {$endif}

 {$ifdef Deb_crt}
  writeln('Prosim pockejte na ukonceni procesu');
 {$endif}

  { zruseni komunikacniho procesu }
  if not TheWinCom.DestroyProcess then
  begin
   {$ifdef Deb_crt}
    Writeln('Proces nelze zrusit');
   {$endif}
    RunError(255);
  end;

  { zruseni procesu zapisujiho do archivu }
  DestructWriteToArchive;

  { odpojeni objektu vizualizace }
 {$ifdef ARCHIVE2}
  if not TheWinCom.UnRegister(pTheArchive2) then
  begin
   {$ifdef Deb_crt}
    writeln('Objekt nelze vyjmout ze smycky zpracovani');
   {$endif}
    RunError(255);
  end;
  Dispose(pTheArchive2, Done);
 {$endif}
 {$ifdef ARCHIVE1}
  if not TheWinCom.UnRegister(pTheArchive1) then
  begin
   {$ifdef Deb_crt}
    writeln('Objekt nelze vyjmout ze smycky zpracovani');
   {$endif}
    RunError(255);
  end;
  Dispose(pTheArchive1, Done);
 {$endif}
 {$ifdef PARAM}
  if not TheWinCom.UnRegister(pTheParam) then
  begin
   {$ifdef Deb_crt}
    writeln('Objekt nelze vyjmout ze smycky zpracovani');
   {$endif}
    RunError(255);
  end;
  Dispose(pTheParam, Done);
 {$endif}
 {$ifdef LOADER}
  if not TheWinCom.UnRegister(pTheLoader) then
  begin
   {$ifdef Deb_crt}
    writeln('Objekt nelze vyjmout ze smycky zpracovani');
   {$endif}
    RunError(255);
  end;
  Dispose(pTheLoader, Done);
 {$endif}
 {$ifdef FILE2}
  if not TheWinCom.UnRegister(pTheFile2) then
  begin
   {$ifdef Deb_crt}
    writeln('Objekt nelze vyjmout ze smycky zpracovani');
   {$endif}
    RunError(255);
  end;
  Dispose(pTheFile2, Done);
 {$endif}
 {$ifdef FILE1}
  if not TheWinCom.UnRegister(pTheFile1) then
  begin
   {$ifdef Deb_crt}
    writeln('Objekt nelze vyjmout ze smycky zpracovani');
   {$endif}
    RunError(255);
  end;
  Dispose(pTheFile1, Done);
 {$endif}

  { uzavreni komunikacniho kanalu }
  TheWinCom.Close;

  { zruseni retezce komunikacnich objektu }
  TheWinCom.DestroyChn;

  { ukonceni vsech procesu }
  Abort('*');

  { ukonceni hlavniho procesu }
  TerminateMain;

  { uvolneni struktur potrebnych pro beh aplikace }
  fnAppDone;

 {$ifdef Deb_Crt}
  { prehled o stavu HEAP }
  {$ifdef UDP}
   {$ifdef DEBUG_ALLOCATIONS}
    Writeln('Heap(start): ', HeapSize, ', Heap(end): ', MemAvail,
           '; (CoBase:',XX_ReqMem,',',XX_PktMem,')');
   {$else}
    Writeln('Heap(start): ', HeapSize, ', Heap(end): ', MemAvail)
   {$endif}
  {$else}
   Writeln('Heap(start): ', HeapSize, ', Heap(end): ', MemAvail);
  {$endif}
 {$endif}
end.

