unit Esemeny;

interface

uses Graphics;

const MotorX         = '0';
      MotorY         = '1';
      MotorS         = '2';

      SensorX        = 0;
      SensorY        = 1;
      SensorS        = 2;

      MaxX           = 100;
      MaxY           = 170;
      NagyitX        = 3;
      NagyitY        = 3;

      {SystemSound}
      ssKeyClick     = 0;
      ssBeepBeep     = 1;
      ssDecFreqSweep = 2;
      ssIncFreqSweep = 3;
      ssError        = 4;
      ssFastIncSweep = 5;

      {SensorType}
      stNone         = 0;
      stSwitch       = 1;
      stTemperature  = 2;
      stLight        = 3;
      stAngle        = 4;

      {SensorMode}
      smRaw          = 0;  {Long: 0-1023}
      smBoolean      = 1;  {True, False}
      smTransCount   = 2;
      smPeriodCount  = 3;
      smPercent      = 4;
      smCelsius      = 5;
      smFahrenheit   = 6;
      smAngle        = 7;

      {Source}
      scVar          = 0;
      scTimer        = 1;
      scConst        = 2;
      scMotorStatus  = 3;
      scRandomNo     = 4; {...}

      {Sebesseg}
      spFej          = 7;
      spScanner      = 7;

      {Szinek}
      szinHatter     = clBlue;

      EgySec         = 1/(24*60*60);
      toRGB          = 256*256+256+1;
      idoFejMozgas   = 4*EgySec;

type TFejTipus = (fejScanner, fejIras, fejNemIras);

function RendszerTeszt:boolean;
function KalibralasTeszt:boolean;
procedure Scanneles;
procedure KepJavitasa;

procedure MoveTheHead(NewX,NewY:longint);
procedure MoveTheHead2(NewX,NewY:longint);

var IsOKTesztInit     :boolean = false;
    IsOKTesztKalib    :boolean = true;
    IsInitComm        :boolean = false;
    IsScanneles       :boolean = false;
    IsKalibralas      :boolean = false;
    IsResetHead       :boolean = false;
    dtxp              :TDateTime = 0.00014108796312939;
    dtxn              :TDateTime = 0.00014305555669125;
    dtyp              :TDateTime = 0.00022442130284617;
    dtyn              :TDateTime = 0.00022118055494502;
    AktX              :longint = 0;
    AktY              :longint = 0;

implementation

uses Forms, SysUtils, SPIRITLib_TLB, Controls,
     Main, Vezerles;

function RendszerTeszt:boolean;

   function InitItems:boolean;
   begin
      InitItems := true;
      with MainForm.SP do begin
         Off(MotorX+MotorY+MotorS);

         SetSensorType(SensorX, stSwitch);
         SetSensorType(SensorS, stLight);
         SetSensorType(SensorY, stSwitch);

         SetSensorMode(SensorX, smBoolean, 0);
         SetSensorMode(SensorS, smRaw, 0);
         SetSensorMode(SensorY, smBoolean, 0);
      end;
   end;

   procedure InitMainForm;
   begin
      with MainForm do begin
         BBSCStart.Enabled := true;
         BBSCStop.Enabled  := false;
      end;
   end;

begin
   MainForm.SP.ComPortNo := 1;
   MainForm.SP.LinkType  := 0;
   MainForm.SP.PBrick    := 1;

   RendszerTeszt := false;
   if MainForm.SP.InitComm then begin
{      if MainForm.SP.TowerAndCableConnected then begin
         if MainForm.SP.TowerAlive then begin
            if MainForm.SP.PBAliveOrNot then begin}
               InitItems;
               InitMainForm;
               MainForm.SP.PlaySystemSound(ssFastIncSweep);
               Application.MessageBox('Minden OK!','Információ',64);
               RendszerTeszt := true;
{            end else Application.MessageBox('Kommunikációs hiba!','Hiba!',16);
         end else Application.MessageBox('A torony nem működik megfelelően!','Hiba!',16);
      end else Application.MessageBox('A torony nem elérhető!','Hiba!',16);}
   end else Application.MessageBox('Nem lehet a kommunikáicót inicializálni!','Hiba!',16);
end;

function KalibralasTeszt:boolean;
begin
   KalibralasTeszt := false;
   if IsOKTesztInit then begin
      IsKalibralas := true;
      MainForm.BBKalibralStart.Enabled := false;
      MainForm.BBKalibralStop.Enabled  := true;

      Vezerles.Kalibralas;

      MainForm.SP.PlaySystemSound(ssFastIncSweep);

      MainForm.BBKalibralStart.Enabled := true;
      MainForm.BBKalibralStop.Enabled  := false;

      KalibralasTeszt := IsKalibralas;
      if IsKalibralas then Application.MessageBox('Kalibrálás OK!','Információ',64)
                      else Application.MessageBox('Kalibrálás nem OK!','Hiba!',16);
      IsKalibralas    := false;
   end else Application.MessageBox('Előbb futtassa a "Rendszer ellenőrzés"-t!','Hiba!',16);
end;

procedure Scanneles;

   procedure ResetImage;
   var i     :longint;
   begin
      MainForm.RE.Lines.Add('Kép törlése...');
      MainForm.RE.Refresh;
      MainForm.Gauge.MinValue := 0;
      MainForm.Gauge.Progress := 0;
      MainForm.Gauge.MaxValue := MainForm.Image.Width;
      MainForm.Gauge.Visible  := true;
      MainForm.Image.Canvas.Pen.Color := szinHatter;
      for i:=0 to MainForm.Image.Width-1 do begin
         MainForm.Image.Canvas.MoveTo(i,0);
         MainForm.Image.Canvas.LineTo(i,MainForm.Image.Height-1);
         MainForm.Gauge.AddProgress(1);
         MainForm.Gauge.Refresh;
      end;
      MainForm.Gauge.Visible := false;
      MainForm.Image.Refresh;
   end;

   procedure ScannelesInicializalasa;
   begin
      MainForm.BBSCStart.Enabled     := false;
      MainForm.BBSCStop.Enabled      := true;
      MainForm.BBKepJavitas.Enabled  := false;
      MainForm.BBKepBetoltes.Enabled := false;
      MainForm.BBKepMentes.Enabled   := false;
      MainForm.SPScanSeb.Enabled     := false;
      MainForm.RE.Lines.Clear;
      MainForm.LIdoEltelt.Caption    := '';
      MainForm.LIdoHatra.Caption     := '';
      MainForm.LIdoOssz.Caption      := '';

      ResetImage;
      MainForm.RE.Lines.Add('Scanner fej beállítása');
      MainForm.RE.Refresh;
      Vezerles.FejBeallit(fejScanner,idoFejMozgas);
      MainForm.RE.Lines.Add('Fej kezdeti pozícióba állítása');
      MainForm.RE.Refresh;
      Vezerles.ResetHead;

      MainForm.RE.Lines.Add('Scannelés...');
      MainForm.RE.Refresh;
      MainForm.Gauge.MinValue := 0;
      MainForm.Gauge.Progress := 0;
      MainForm.Gauge.MaxValue := MaxY;
      MainForm.Gauge.Visible  := true;
   end;

   procedure ScannelesLezarasa;
   begin
      if IsScanneles then MainForm.RE.Lines.Add('Scannelés OK!')
                     else MainForm.RE.Lines.Add('Scannelés megszakítva!');
      MainForm.Gauge.Visible := false;

      MainForm.RE.Lines.Add('Fej kezdeti pozícióba állítása');
      Vezerles.ResetHead;
      MainForm.BBSCStart.Enabled     := true;
      MainForm.BBSCStop.Enabled      := false;
      MainForm.BBKepJavitas.Enabled  := true;
      MainForm.BBKepBetoltes.Enabled := true;
      MainForm.BBKepMentes.Enabled   := true;
      MainForm.SPScanSeb.Enabled     := true;
   end;

   function toColor(v :longint) :TColor;
   begin
      v := 980 - v;
      result := v*toRGB;
   end;

   procedure Rajzolas(Sor:longint; dts,dte,dta:TDateTime; Val, Elt:longint);
   var Szin        :TColor;
       Oszl, i, j  :longint;
   begin
      Szin := toColor(Val);

      Oszl := Round((dta-dts)*MaxX/(dte-dts));

      for i:=0 to NagyitX-1 do
         for j:=0 to NagyitY-1 do
            MainForm.Image.Canvas.Pixels[(Oszl+Elt)*NagyitX+i,Sor*NagyitY+j] := Szin;
   end;

type TValue = record
                 value    :longint;
                 time     :TDateTime;
              end;
     TValues = array[1..1000] of TValue;
var i, j, db, elt                   :longint;
    ok                              :boolean;
    dts, dte, tx,
    dtstart, dtelt, dtossz          :TDateTime;
    v                               :TValues;
begin
   if IsOKTesztInit then begin
      if IsOKTesztKalib then begin
         if Application.MessageBox('Biztosan kéri a kép scannelését?','Kérdés',36)=mrYes then begin
            ScannelesInicializalasa;

            IsScanneles := true;
            i           := 0;
            dtstart     := now;
            MainForm.SP.SetPower(MotorY,scConst,spScanner);
            MainForm.SP.SetPower(MotorX,scConst,MainForm.SPScanSeb.Value);
            MainForm.SP.SetFwd(MotorY);
            while (i<MaxY) and (IsScanneles) do begin
               if i mod 2 = 0 then begin
                  MainForm.SP.SetFwd(MotorX);
                  tx  := dtxp/2;
               end else begin
                  MainForm.SP.SetRwd(MotorX);
                  tx  := dtxn/2;
               end;
               dts := now;
               ok  := true;
               db  := 0;
               MainForm.SP.On_(MotorX);
               while ok do begin
                  inc(db);
                  v[db].value := GetSensorRaw(SensorS);
                  v[db].time  := now-dts;
                  ok := (now<dts+tx) or (GetSensorBoolean(SensorX)=0) and IsScanneles;
                  Application.ProcessMessages;
               end;
               MainForm.SP.Off(MotorX);

               if i mod 2 = 0 then begin
                  dts := v[1].time;
                  dte := v[db].time;
                  elt := -2;
               end else begin
                  dts := v[db].time;
                  for j:=1 to db do v[j].time := dts-v[j].time;
                  dts := v[db].time;
                  dte := v[1].time;
                  elt := 2;
               end;

               for j:=1 to db do Rajzolas(i,dts,dte,v[j].time,v[j].value,elt);

               MotorVezerlesTime(MotorY,(1/MaxY)*dtyp,true);
               Varakozas(2*EgySec);
               inc(i);
               MainForm.Gauge.AddProgress(1);
               dtelt  := now-dtstart;
               dtossz := dtelt*MaxY/i;
               MainForm.LIdoEltelt.Caption := TimeToStr(dtelt);
               MainForm.LIdoOssz.Caption   := TimeToStr(dtossz);
               MainForm.LIdoHatra.Caption  := TimeToStr(dtossz-dtelt);
               Application.ProcessMessages;
            end;

            ScannelesLezarasa;
         end;
      end else Application.MessageBox('Előbb kalibrálni kell a scannert!','Hiba!',16);
   end else Application.MessageBox('Előbb futtassa a "Rendszer ellenőrzés"-t!','Hiba!',16);
end;

procedure KepJavitasa;

   procedure Kitoltes(Sor, Kezd, Vege, OldSzin, NewSzin:longint);
   var i, j, Szin  :longint;
   begin
      OldSzin := OldSzin div toRGB;
      NewSzin := NewSzin div toRGB;
      for i:=Kezd to Vege do begin
         Szin := Round(OldSzin+(NewSzin-OldSzin)*(i-Kezd+1)/(Vege-Kezd+2));
         for j:=Sor*NagyitY to Sor*NagyitY+NagyitY-1 do MainForm.Image.Canvas.Pixels[i,j] := Szin*toRGB;
      end;
   end;

   procedure KepJavitas(Sor:longint);
   var i, j              :longint;
       OldSzin, NewSzin  :longint;
   begin
      OldSzin := -1;
      i       := 0;
      while i<=MainForm.Image.Width-1 do begin
         if MainForm.Image.Canvas.Pixels[i,Sor*NagyitY]=szinHatter then begin
            j := i+1;
            while (MainForm.Image.Canvas.Pixels[j,Sor*NagyitY]=szinHatter) and (j<=MainForm.Image.Width-1) do inc(j);
            if j<=MainForm.Image.Width-1 then NewSzin := MainForm.Image.Canvas.Pixels[j,Sor*NagyitY]
                                         else NewSzin := -1;
            if OldSzin=-1 then OldSzin := NewSzin;
            if NewSzin=-1 then NewSzin := OldSzin;

            if NewSzin<>-1 then Kitoltes(Sor,i,j-1,OldSzin,NewSzin);
            i := j;
         end else begin
            OldSzin := MainForm.Image.Canvas.Pixels[i,Sor*NagyitY];
            inc(i);
         end;
      end;
   end;

var i     :longint;
begin
   if Application.MessageBox('Biztosan kéri a kép javítását?','Kérdés',36)=mrYes then begin
      MainForm.RE.Lines.Add('Kép minőségének javítása...');
      MainForm.Gauge.MinValue := 0;
      MainForm.Gauge.Progress := 0;
      MainForm.Gauge.MaxValue := MaxY;
      MainForm.Gauge.Visible  := true;
      for i:=0 to MaxY do begin
         KepJavitas(i);
         MainForm.Gauge.AddProgress(1);
         MainForm.Refresh;
      end;
      MainForm.Gauge.Visible  := false;
   end;
end;

{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------}
{------------------------------------------------------------------------------}

procedure MoveTheHead(NewX,NewY:longint);
var dx, dy      :longint;
    tx, ty      :TDateTime;
begin
{Szamitas}
   dx := NewX-AktX;
   dy := NewY-AktY;
   if dx<0 then begin
      MainForm.SP.SetRwd(MotorX);
      tx := (abs(dx)/MaxX)*dtxn;
   end else begin
      MainForm.SP.SetFwd(MotorX);
      tx := (abs(dx)/MaxX)*dtxp;
   end;
   if dy<0 then begin
      MainForm.SP.SetRwd(MotorY);
      ty := (abs(dy)/MaxY)*dtyn;
   end else begin
      MainForm.SP.SetFwd(MotorY);
      ty := (abs(dy)/MaxY)*dtyp;
   end;
   MainForm.SP.SetPower(MotorX+MotorY,scConst,spScanner);

   if dx<>0 then Vezerles.MotorVezerlesTime(MotorX,tx,true);
   if dy<>0 then Vezerles.MotorVezerlesTime(MotorY,ty,true);
   AktX := NewX;
   AktY := NewY;
end;

procedure MoveTheHead2(NewX,NewY:longint);
var dx, dy                 :real;
    tx, ty                 :TDateTime;
    cikl, i                :longint;
begin
   dx := NewX-AktX;
   dy := NewY-AktY;
   if abs(dx)<abs(dy) then begin
      if dx=0 then begin
         Cikl := 1;
         dx   := dx;
         dy   := dy;
      end else begin
         Cikl := round(abs(dx));
         dy   := dy/abs(dx);
         dx   := round(dx/abs(dx));
      end;
   end else begin
      if dy=0 then begin
         Cikl := 1;
         dx   := dx;
         dy   := dy;
      end else begin
         Cikl := round(abs(dy));
         dx   := dx/abs(dy);
         dy   := round(dy/abs(dy));
      end;
   end;
   if dx<0 then begin
      MainForm.SP.SetRwd(MotorX);
      tx := (abs(dx)/MaxX)*dtxn;
   end else begin
      MainForm.SP.SetFwd(MotorX);
      tx := (abs(dx)/MaxX)*dtxp;
   end;
   if dy<0 then begin
      MainForm.SP.SetRwd(MotorY);
      ty := (abs(dy)/MaxY)*dtyn;
   end else begin
      MainForm.SP.SetFwd(MotorY);
      ty := (abs(dy)/MaxY)*dtyp;
   end;
   MainForm.SP.SetPower(MotorX+MotorY,scConst,spScanner);

   for i:=1 to Cikl do begin
      if dx<>0 then Vezerles.MotorVezerlesTime(MotorX,tx,true);
      if dy<>0 then Vezerles.MotorVezerlesTime(MotorY,ty,true);
   end;
   AktX := NewX;
   AktY := NewY;
end;

end.
