Programmet

En beskrivelse af programmet og dets funktioner


Programmet i RasPi'en vil komme til at bestå af alle de dele, der skal til for at kunne styre stationen via kontroltavlen. Men da meget af det elektriske på banen ikke er klar til alle detaljer, så vil programmet være begrænset til at udføre de mest vigtige ting - for nu. Det, der mangler, er sporføling. Dette er dog på tegnebrættet, og noget af det elektriske er allerede klargjort til dette.

Programmet er heller ikke optimeret og finpudset. Mange ting kan gøres mere effektivt, tidssparende og overskueligt, og det er specielt gentagne funktioner, der tænkes på. Dette vil dog ske løbende. Det har i første omgang gjaldt om at få tingene til at virke. Så må finpudsningen komme senere.

Programmet er delt op i mange Procedurer og Functions. Disse vil blive beskrevet herunder.

Programmet indeholder også mange kald til at skrive i filer - såkaldte Writeln. Disse skriver data ind i en tekstfil, som senere kan åbnes og læses. Dette skal bruges til de situationer, hvor der er problemer - hvor tingene ikke lige sker som forventet. Man kan så læse i log-filen og se, om man kan finde problemet, så man kan få det rettet.


Gå til


"Uses", konstanter og variable

Første deklaration er alle de tillægsprogrammer, "Units", der skal bruges til at få det hele til at virke.

Den øvre linie er alle dem, der definerer stationen og dens spor, signaler og hvad der ellers er - og tilhørende ting:
  • sporplan: Alle sporene og deres forbindelser i tabelform
  • foelere: Sporfølere og deres adresser (endnu ikke implementeret)
  • sporskft: Sporskiftestillinger for hver enkelt køremulighed per sporskifte og kryds
  • knapper: Hver enkelt knaps tilknytning til spor per knapnummer
  • sporskln: Hvert sporskiftes LocoNet adresse
  • Fejlkoder: Til at fortælle, hvilken fejl der er blevet detekteret/begået
  • Aussentaster: Knapper til alt det ekstra, der kan foregå med hensyn til betjening af sporveje osv., bl.a. fortrydelse/opløsning af sporveje, låsning af sporskifter og signaler og meget mere . . .
Den næste linie er de Units, der har med operativsystemet og RasPien at gøre - også de 40 pins:
  • crt, baseUnix, Classes, SysUtils: Units, biblioteker, til alt det, hvor selve RasPiens funktionaliteter skal bruges.
  • h2wiringpi: Special-unit til at få programmet til at arbejde med de 40 IO pins.
h2wiringpi er ikke et stsndard bibliotek. Det er udviklet af en programmør, der hedder xxxx. Projektet kan findes her:

https://github.com/laz2wiringpi/laz2wiringpi/blob/master/h2wiringpi.pas
https://bigdanzblog.wordpress.com/2014/01/21/accessing-raspberry-pi-gpio-using-lazarusfree-pascal/ - En lille tutorial

CONST

Her er der defineret konstanter: Tal, der er faste, men vi giver dem et navn, så koden bliver nemmere at læse og forstå.

VAR

Der er defineret mange variabler. Mange af dem er Arrays, som bruges til at lave skemaer ("databaser") med. Og der er flere endnu, men de er defineret i de Units, der bliver brugt. Det er i Unit'sene, hvor stationen og alle dens spor, sporskiftere og tilhørende elementer er beskrevet. De variable, der bliver defineret her, er dem, der kan variere i værdi, alt efter hvad der skal ske - og sker - på stationen.


USES    {$IFDEF UNIX}{$IFDEF UseCThreads}
         cthreads,
        {$ENDIF}{$ENDIF}
      sporplan, foelere, sporskft, knapper, sporskln, Fejlkoder, Aussentaster,
      crt, baseUnix, Classes, SysUtils, h2wiringpi;

//??  Forms, Controls, Graphics, Dialogs, Interfaces;



CONST
{*****}
 AntalKnapper  = 416;  { Tre knapprint plus de to første rækker af det fjerde. }
 AntalKnapStik = 32;   { 8 stik på hver print. 4 print ialt. }
 holdt         = $08;
 koer          = $01;
 langsomt      = $04;
 ranger        = $02;
 w_lige        = $01;
 w_drej        = $02;
 Plank         = true;
 Rangerk       = false;
 I2C_SLAVE     = 1795;


 VAR

   Sporskema            :  ARRAY [1..16,1..32] OF LongInt;  {[sporbloknr, trin]}
   Sporskemanr          :  Byte;

   signal               :  ARRAY [false..true, 0..501] OF BYTE;      {[retning, blok]}

   sporskifteskema      :  ARRAY [1..16, 1..32]   OF LongInt;        { [sporvej nr , trin]: }
   sporskiftestilling   :  ARRAY [1051..1200]     OF Integer;        {Sporskiftets nuværende stilling}
                                                                     { 1 = lige ud, 0 = afvigende  }
   sporskiftelaast      :  ARRAY [191..320, 1..8] OF Boolean;        {Er sporskiftet låst eller ej}
   sporskiftemanlaast   :  ARRAY [191..320, 1..8] OF Boolean;        {Er sporskiftet manuelt låst eller ej}
   sporskifteskemaSkift :  ARRAY [1..16, 1..16]   OF Boolean;        { [sporvej nr , trin]: Bruges til at styre skiftet
									Værdi + false = Sporskifter fundet, men ikke stillet
									Værdi + True  = Ordere om at skifte er sendt.
									Herefter slettes tallene, efterhånden som tilbagemeldiner kommer ind}

//   InputStak            :  ARRAY [1..15] OF Word;                    {Indl?e aktive knapper  }
   Outputstak           :  ARRAY [1..15] OF Word;
   KnapInd              :  Array [1..AntalKnapper] of integer;  // Knapper indlæst fra kontroltavle: Status p?lle knapper - betjent/ikke betjent
   Knap1                :  Word;
   Knap2                :  Word;
   Retning              :  Boolean;
   Koerselstype         :  Boolean;

   Midterknap           :  ARRAY [false..true, 1291..1299] OF BYTE;  {[retning, blok]}
                                                                     {P?tationen kan man benytte en halvdel af sporet }
   Vejfundet1           :  Array [0..1,1..32] of WORD;
   Vejfundet2           :  Array [0..1,1..32] of WORD;
   RetningSPST          :  Array [1..32] of Boolean;
   Sporskifterfundet1   :  Array [1..32] of Integer;
   Sporskifterfundet2   :  Array [1..32] of Integer;
   trin                 :  Byte;
   
   PU                   :  array [1..4] of char;
   PI                   :  array [1..4] of char;
   OpCodeInput          :  array [1..4] of char;
   Adresse              :  longint;
   Spsk_Adresse         :  longint;
   Spsk_Adresse1        :  longint;
   Spsk_DIRetning       :  longint;
   Spsk_ONoutput        :  longint;
   Blok_Adresse         :  longint;
   Blok_InputSource     :  Integer;
   Blok_SensorLevel     :  Integer;
   Blok_InputSourceI    :  Integer;
   Blok_SensorLevelI    :  Integer;
   Xcb                  :  longint;
   devPath              :  string = '/dev/i2c-1';
   handleLN             :  Cint;
   handleTL             :  Cint;
   LEDSpSk              :  array [1..4] of char;
   LocoNet              :  Cint = $11;
   Tavlelys             :  Cint = $12;
   LEDStilling          :  integer;

   UData, UCl, USTR     :  integer;
   IData, ICl, ISTR     :  integer;
   Knaprow, Knapcolomn  :  integer;
   InputMem1, InputMem2 :  Integer;
   Knapperlaest         :  Array [1..3] of integer;
   KnapperTrykket       :  Boolean;
   Knapx1               :  longint;

      

   x, y, z              :  Word;
   a, b ,c              :  Word;
   xa, ya, za           :  WORD;
   xb, yb, zb           :  WORD;
   tx, ty, tz           :  char;

   SpskStakFIFO   : array [1..40, 1..3] of longint;
                                 {1:Adresse 2:DIR 3:ON}
   SpskStakFIFOST      :  integer;
   SpskStakFIFOSL      :  integer;
   SpskStakFIFODelay   :  integer;


   F : Text;   {Til at skrive i fil / testing  }
   L : Text;   { Logging }
   Logdate  :  string;

   KBValg1       : Char;


Function HexB ( b : byte) : String;

Denne Function bruges i forbindelse med LocoNet dataoverførsel.

Når data sendes via LocoNet, skal der sendes Hexadecimale tal; altså tal, de har "basis 16" ( og ikke 10, som vi normalt bruger). Så tallene går fra "01" til "FF". Og når disse sendes, så skal der være to karakterer. Dene funktion kreerer disse to karakterer ud fra det tal, vi beder funktionen om at lave om.


  Function HexB ( b : byte) : String;
  Const
       HexChar : array[0..15] of char = '0123456789ABCDEF';
  begin
       HexB := '$' + Hexchar[b shr 4] + HexChar[b and $0F];
  end;
   

procedure SpskStakFIFOPOP;

Denne procedure fungerer sammen med den næste procedure; SpskStakFIFOPUSH.

Dens funktion er at skrive de LocoNet kommandoer til sporskiftere ud på LocoNettet, som der er i bufferen. Dette gøres efter "First in -> First Out" - princippet. Formålet er to ting.

Den første er at sikre, at LocoNet-komandoerne ikke bliver sendt afsted lige med det samme. Uden denne buffer ville LocoNet ikke kunne håndtere, hvis RasPien/programmet "bare" sendte dem afsted, efterhånden som de blev "genereret" af programmet. For LocoNet ville det se ud som om, at de alle blev sendt afsted samtidig, og så kan LocoNet ikke skelne dem fra hinanden.

Den anden grund er, at i virkeligheden skifter sporskifterne ikke samtidigt. Det kan måske godt se sådan ud, når man står og kigger. Men der er en lille pause imellem hver initiering af et skift. Dette skyldes, at der bruges en stor startstrøm, en strømpuls, når et sporskifte går i gang med at skifte. Ved at sprede starten på skiftene lidt ud tidsmæssigt, undgår man, at disse pulser kommer samtidigt. Hvis de gjorde det, ville det belaste el-nettet ret enormt. Denne lille detalje er med her.


procedure SpskStakFIFOPOP;     {Udlæs fra stak}
begin
Spsk_Adresse := SpskStakFIFO[SpskStakFIFOST,1];    {Adresse}
 Spsk_DIRetning := SpskStakFIFO[SpskStakFIFOST,2];  {DIR}
  Spsk_ONoutput  := SpskStakFIFO[SpskStakFIFOST,3];  {ON}

if (Spsk_Adresse <> 0) and (SpskStakFIFODelay = 0 ) then begin
   SpskStakFIFO[SpskStakFIFOST,1] := 0;  {Adresse}
   SpskStakFIFO[SpskStakFIFOST,2] := 0;  {DIR}
   SpskStakFIFO[SpskStakFIFOST,3] := 0;  {ON}

   SpskStakFIFOST := SpskStakFIFOST + 1;
   if SpskStakFIFOST = 41 then SpskStakFIFOST := 1;

   Write(L, 'SPSK Pop: Adresse = ', Spsk_Adresse,' ', Spsk_DIRetning,' ', Spsk_ONoutput ,'.  ',
          WeicheLN[Spsk_Adresse,0],',',WeicheLN[Spsk_Adresse,1]);
   Write('SPSK Pop: Adresse = ', Spsk_Adresse,' ', Spsk_DIRetning,' ', Spsk_ONoutput ,'.  ',
          WeicheLN[Spsk_Adresse,0],',',WeicheLN[Spsk_Adresse,1]);

 {Skriv til Loconet:}
    Spsk_Adresse1 := Spsk_Adresse - 1;
    PU[1] := chr($B0);
    PU[2] := chr((Spsk_Adresse1) and $7F);
    PU[3] := chr(((Spsk_Adresse1 and $780) shr 7) + (Spsk_ONoutput shl 4) + (Spsk_DIRetning shl 5));
    PU[4] := chr(not ($B0
                 xor ((Spsk_Adresse1) and $7F)
                 xor ((((Spsk_Adresse1 and $780) shr 7) + (Spsk_ONoutput shl 4) + (Spsk_DIRetning shl 5)) and $FF)));

// I2C
    try
        fpwrite(handleLN, PU, 4); 
    except
        writeln('Error writing');
        halt;
    end; //try
    sleep(50);

// Send 00 til LEDs
    LEDSpSk[1] := chr(1);
    LEDSpSk[2] := chr(Spsk_Adresse-1050);
    LEDSpSk[3] := chr(4);
    try
       fpwrite(handleTL, LEDSpSk, 4);
    except
       writeln('Error writing');
       halt;
    end; //try
    sleep(50);
	

    WRITELN(L, 'POP Sent : '+PU[1]+ ' '+ PU[2]+ ' '+ PU[3]+ ' '+ PU[4]);
    writeln(L, 'Writing ledspsk: ', LEDSpSk[1], '.', LEDSpSk[2], '.', LEDSpSk[3], ' : ', x);writeln;
    WRITELN('POP Sent : '+PU[1]+ ' '+ PU[2]+ ' '+ PU[3]+ ' '+ PU[4]);
    writeln('Writing ledspsk: ', LEDSpSk[1], '.', LEDSpSk[2], '.', LEDSpSk[3], ' : ', x);writeln;

   SpskStakFIFODelay := 0;
end
else if SpskStakFIFODelay > 0 then Dec(SpskStakFIFODelay);
end;
   

procedure SpskStakFIFOPUSH;

Denne procedure skriver data ind i bufferen beskrevet i afsnittet herover.

Data hertil kommer fra de procedurer, der har fundet en sporvej med tilhørende sporskiftestillinger. Sporskiftestillingerne skal sendes ud til sporskifterne, så sporvejen kan udføres, og det gøres via denne procedure.


procedure SpskStakFIFOPUSH;    {Indlæs til stak}
begin
if SpskStakFIFO[SpskStakFIFOSL, 1] = 0 then begin

   SpskStakFIFO[SpskStakFIFOSL, 1] := Spsk_Adresse;
   SpskStakFIFO[SpskStakFIFOSL, 2] := Spsk_DIRetning;
   SpskStakFIFO[SpskStakFIFOSL, 3] := Spsk_ONoutput;

   SpskStakFIFOSL := SpskStakFIFOSL + 1;
   if SpskStakFIFOSL = 41 then SpskStakFIFOSL := 1;
   end
   else
   Writeln(L, 'SpSkStakFIFO er fuld !!!  :', SpskStakFIFOSL);
end;
   

function skiftspor(spsknu:word):word;

Det er også muligt - selvfølgelig - at nøjes med bare at skifte et sporskifte. Det sørger denne function for.

Denne funktion bruger ikke den ovennævnte buffer. Lige nu er behovet der ikke direkte, idet man kun skifteret enkelt sporskifte. Så der er reelt ikke behov for bufferens funktionalitet. Men det vil nok blive lavet om på et tidspunkt.

En anden grund er, at det var noget af det første, der blev lavet. Og det har fået lov til at forblive sådan, mens alt det andet blev lavet.


function skiftspor(spsknu:word):word;
Label 1;

VAR
  UpCode1, Adresse1, Adresse2, CheckSum, err   : Integer;

BEGIN

writeln(L, ' SkiftSporNu Start -------------------------');
writeln(L,  '  spsknu = ', spsknu);
write(L,  ' WeicheLN[Knap[spsknu],0] = ', WeicheLN[Knap[spsknu],0], '.', WeicheLN[Knap[spsknu],1]);
writeln(L,  ' :: stilling=', sporskiftestilling[Knap[Spsknu]]);

{Denne funktion skifter et sporskifte med det samme,
hvis det kan lade sig g›re}
{Check, om sporet er optaget}
 for x := 1 to 16 do begin
     for y := 1 to 32 do begin
         if WeicheLN[Knap[spsknu],0] = sporskema[x,y] then begin
            fejl := 9;
            goto 1;
         end;
     end;
 end;

 {Check, om sporet er l†st/blokeret}

{ Data (måske) enten fra knap eller fra fundet sporvej }

  {Hent stilling fra intern database}
     Spsk_Adresse := Knap[Spsknu];
//     Spsk_ONoutput := 1;
write(L, 'Stilling: ', sporskiftestilling[Spsk_Adresse],' - ');
      if sporskiftestilling[Spsk_Adresse] = 2 then Spsk_DIRetning := 1;
      if sporskiftestilling[Spsk_Adresse] = 1 then Spsk_DIRetning := 0;
      writeln(' -> ', sporskiftestilling[Spsk_Adresse]);

  {Skriv til Loconet:}
  Spsk_Adresse1:=Spsk_Adresse-1;
  PU[1] := chr($B0);
   PU[2] := chr((Spsk_Adresse1) and $7F);
    PU[3] := chr(((Spsk_Adresse1 and $780) shr 7) + (1 shl 4) + (Spsk_DIRetning shl 5));
    PU[4] := chr(not ($B0
                 xor ((Spsk_Adresse1) and $7F)
                 xor ((((Spsk_Adresse1 and $780) shr 7) + (1 shl 4) + (Spsk_DIRetning shl 5)) and $FF)));

Val(HexB(Ord(PU[1])), UpCode1, err);
Val(HexB(Ord(PU[2])), Adresse1, err);
Val(HexB(Ord(PU[3])), Adresse2, err);
Val(HexB(Ord(PU[4])), CheckSum, err);
        writeln(L);
        writeln(L, 'B0 start -----------------------------------------------');
    	writeln(L, 'B0:  Val-> ', UpCode1,' ', Adresse1,' ', Adresse2,' ', CheckSum);



//    WRITELN('Sent, 1 : '+PU[1]+ ' '+ PU[2]+ ' '+ PU[3]+ ' '+ PU[4]);

//I2C
    try
        fpwrite(handleLN, PU, 4); 
    except
        writeln('Error writing');
        halt;
    end; //try
    sleep(50);
	
// Send 00 til LEDs
    LEDSpSk[1] := chr(1);
    LEDSpSk[2] := chr(SpSk_Adresse-1050);
    LEDSpSk[3] := chr(0);
    try
       fpwrite(handleTL, LEDSpSk, 4);
    except
       writeln('Error writing');
       halt;
    end; //try
    sleep(50);
	

    WRITELN(L, 'Sent, 2 : '+PU[1]+ ' '+ PU[2]+ ' '+ PU[3]+ ' '+ PU[4]);
    writeln(L, 'Writing ledspsk: ', ord(LEDSpSk[1]), '.', ord(LEDSpSk[2]), '.', ord(LEDSpSk[3]), ' : ', SpSk_Adresse);
   //   if Spsk_DIRetning = 1 then sporskiftestilling[Spsk_Adresse] := 1;

1:
writeln(L, ' SkiftSporNu slut . . . ----------------------------');
end;
   

procedure init;

Denne procedure sætter alt det op, der er behov for, for at få det hele til at virke:
  • Indlæsning af alle Unit'sene, hvor stationens "data" er beskrevet
  • Initiering af I2C, så RasPi kan "tale" med Arduinoerne
  • Indlæsning af alle sporskifter, så "vi" ved, hvilken stilling de står i
  • Initiering af RasPiens porte, så knapper kan indlæses


procedure init;

Label 1, 2, 99;

  var
   OpCodeInputI : String;
   UpCode1I     :  integer;
   AdresseI     :  integer;
   Adresse1I    :  integer;
   Adresse2I    :  integer;
   CheckSumI    :  integer;
   errI         :  integer;
   Stilling     :  integer;

    Fil     :    Text;

  begin

      writeln(' *** Starter initiering ***');
  	initsporplan;
        initsporskifts;
	initknapperP;
	initknapperR;
        initknapperSPSK;
        initspskLN;
        initLNspsk;
       {* initfoelere; *}


        FEJL:=0;
        FOR y:=1 to 32 do begin
            for x:=1 to 16 do Sporskema[x,y]:=0;
        END;  x:=1; y:=1;

        Knap1 := 0;
        Knap2 := 0;

        for x:= 1 to 40 do begin
            for y:= 1 to 3 do SpskStakFIFO[x,y] := 0;
        end;
        SpskStakFIFOST := 1;
        SpskStakFIFOSL := 1;
        SpskStakFIFODelay := 1;

//I2C  Init
    try
       handleTL := fpopen(devPath,O_RDWR);
       fpIOCtl(handleTL, I2C_SLAVE, pointer(TavleLys));
       writeln('I2C Tavlelys successfull !!!');
    except
       writeln('Error initalizing i2c');
       halt;
    end;
     sleep(50);
   try
       handleLN := fpopen(devPath,O_RDWR);
       fpIOCtl(handleLN, I2C_SLAVE, pointer(LocoNet));
       writeln('I2C Loconet successfull !!!');
    except
       writeln('Error initalizing i2c');
       halt;
    end;
    sleep(50);

    tx := '1';   PI[1] :=chr(ord(tx) - ord('0'));
    tx := '0';   PI[2] :=chr(ord(tx) - ord('0'));
    tx := '0';   PI[3] :=chr(ord(tx) - ord('0'));
    tx := '0';   PI[4] :=chr(ord(tx) - ord('0'));

    try
       fpwrite(handleLN, PI, 1);
    except
       writeln('Error writing - writing 1');
       halt;
    end; //try
    sleep(50);

    PI[1] := #99;
    writeln('Done I2C INIT.');

{ Læser alle sporskifter for stilling:   }

    assign(Fil, 'Init spsk stilling.txt'); Rewrite(Fil);

    Spsk_ONoutput := 1;
    Spsk_DIRetning := 1;

    for x := 257 to 300 do begin   { SpSk knapper fra 257 til 384}
        writeln('x = ', x, '      Knap[x] = ', Knap[x]);
	    if Knap[x] > 0 then begin
            Write(Fil, 'For ', x, ': ');
            Writeln('For ', x, ': ');
            Knapx1 := Knap[x]-1;
            PU[1] := chr($BC);
            write(' 1:',HexB(Ord(PU[1])), ' ');
            PU[2] := chr((Knapx1) and $7F);
            write(' 2:',HexB(Ord(PU[2])), ' ');

            PU[3] := chr(((Knapx1 and $780) shr 7) + (Spsk_ONoutput shl 4) + (Spsk_DIRetning shl 5));
            write(' 3:',HexB(Ord(PU[3])), ' ');

            PU[4] := chr(not ($BC
                               xor ((Knapx1) and $7F)
                               xor ( (((Knapx1) and $780) shr 7) + (Spsk_ONoutput shl 4) + (Spsk_DIRetning shl 5) )
                         )    );
            write(' 4:',HexB(Ord(PU[4])), ' ');


//I2C
// Send forespørgsel til sporskifte
2:
            sleep(50);
            try
              fpwrite(handleLN, PU, 4);
              writeln('Writing asking ', Knap[x]+1, ' . . . ');
            except
              writeln('Error writing');
              halt;
            end; //try
            sleep(50);

            WRITEln(Fil, 'Sent : '+PU[1]+ ' '+ PU[2]+ ' '+ PU[3]+ ' '+ PU[4]);
            WRITEln('Sent : '+PU[1]+ ' '+ PU[2]+ ' '+ PU[3]+ ' '+ PU[4]);
            writeln;
// Send 00 til LEDs
            LEDSpSk[1] := chr(1);
            LEDSpSk[2] := chr(x-256);
            LEDSpSk[3] := chr(0);
            writeln('Writing ledspsk: ', LEDSpSk[1], '.', LEDSpSk[2], '.', LEDSpSk[3], ' : ', x);writeln;
            try
              fpwrite(handleTL, LEDSpSk, 4);
              writeln('Writing ledspsk: ', LEDSpSk[1], '.', LEDSpSk[2], '.', LEDSpSk[3], '...', x);writeln;
            except
              writeln('Error writing');
              halt;
            end; //try
            sleep(50);

// Receive
          for z :=25 downto 0 do begin
              try
		fpread(handleLN, PI, 4);
                writeln('fpread . . . ' );
	      except
		writeln('Error reading - loconet data from arduino');
		halt;
	      end; //try
              sleep(50);

              writeln(' Read: 1=',HexB(Ord(PI[1])),' 2=',HexB(Ord(PI[2])),' 3=',HexB(Ord(PI[3])),' 4=',HexB(Ord(PI[4])),' ');
              writeln(' tried . . .   PI[1] = ', HexB(Ord(PI[1])));

                if ord(PI[1]) = $B1 then goto 1;            // $B1
		if z = 1 then goto 2;
	  end;



		  // Response fra sporskifte / Møllehem Servodecoder er ikke modtaget
          fejl := 91;
          goto 99;


// Sporskifte data modtaget
1:
            Writeln(' Received . . . ');

            Val(HexB(Ord(PI[1])), UpCode1I, errI);
            Val(HexB(Ord(PI[2])), Adresse1I, errI);
            Val(HexB(Ord(PI[3])), Adresse2I, errI);
            Val(HexB(Ord(PI[4])), CheckSumI, errI);
			writeln(Fil, ' Val-> ', UpCode1I,' ', Adresse1I,' ', Adresse2I,' ', CheckSumI);
			writeln(     ' Val-> ', UpCode1I,' ', Adresse1I,' ', Adresse2I,' ', CheckSumI);
   //         sleep(5000);
	if (UpCode1I xor Adresse1I xor Adresse2I xor CheckSumI) = $FF then begin
                Blok_SensorLevelI := (Adresse2I and $10) shr 4;  // Sensor level - low/high
                Blok_InputSourceI := (Adresse2I and $20) shr 5;  // Input source - DS54 / switch
                Adresse2I := ((Adresse2I and $F) shl 7);
                AdresseI := Adresse1I + Adresse2I + 1;
 //               Stilling := ((Adresse2I and $10) shr 4);

           If Blok_SensorLevelI = 0 then begin Sporskiftestilling[AdresseI] := 2; LEDstilling := 2; end;
           If Blok_SensorLevelI = 1 then begin Sporskiftestilling[AdresseI] := 1;  LEDstilling := 1; end;

           writeln(Fil, '  Init status: Adresse= ', AdresseI, '  ON/SL=', Blok_SensorLevelI, '  DIR/IS=', Blok_InputSource);
           writeln(     '  Init status: Adresse= ', AdresseI, '  ON/SL=', Blok_SensorLevelI, '  DIR/IS=', Blok_InputSource);



// Send stilling til LEDs
            LEDSpSk[1] := chr(1);
            LEDSpSk[2] := chr(x-256);
            LEDSpSk[3] := chr(LEDstilling);
            sleep(50);
            try
              fpwrite(handleTL, LEDSpSk, 4);
              writeln('Writing spsk . . . ', LEDSpSk[1], ' - ', ord(LEDSpSk[2]), ord(LEDSpSk[1]), ' - ', ord(LEDSpSk[3]), '!!!');
            except
              writeln('Error writing');
              halt;
            end; //try
            sleep(50);
            Writeln(' . . . LED stilling=', ord(LEDSpSk[3]));
			end
			else writeln(Fil, ' Init Checksum Error !!!');
           end;
      Writeln(Fil);
	end;
    Close(Fil);


//Knapper: Initialiserer RasPis ind- og udgange:
        // Raspi pinouts
        UData := 0; UCl := 2; USTR := 3;
        IData := 6; ICl := 5; ISTR := 4;

        //  Init GPIO
        If wiringPiSetup = -1 then begin
          writeln('Setup failed');
          Halt;
        end;

        pinmode (UData, output);
        pinmode (UCl, output);
        pinmode (USTR, output);

        pinmode (IData, input);
        pinmode (ICl, output);
        pinmode (ISTR, output);

        digitalwrite(ICl,LOW);
        digitalwrite(ISTR,LOW);
        digitalwrite(UData,LOW);
        digitalwrite(UCl,LOW);
        digitalwrite(USTR,LOW);
        delay(1);


        writeln(' *** Afslutter initiering ***');
Writeln(L, ' Initiering færdig.');
99:
end;
   

Procedure KnapperLaesInd;

I denne procedure læses alle knapperne ind.

Knapperen er delt ind i grupper:
    Røde knapper: Til at lave sporveje
  • Gule knapper: Til at lave rangerveje
  • Sorte knapper: Til at skifte sporskiftere
  • Grå knapper: Til ekstra og special-funktioner
Knapperne bliver for hver program-rotation læst ind af denne procedure.

Det er her, at Unit'en h2wiringpi bliver benyttet (sammen med initialisationen i Unit'en "Init"). Man kan dog stadig sige, at der skal basal programmering til, fordi der ikke er tale om et simpelt kald til en funktion. Vi skal selv sætte pins høje og lave - alt efter behov. Desværre viste det sig, at det ikke var muligt "bare" at sætte pin'enes stilling, for det viste sig, at selve elektronikken, der udfører selve aflæsningen af knapperne, nemlig kredsene 4014 og 4094 - de viste sig at have en maksimal arbejdshastighed, der var lavere end RasPi'ens ind- og udgange. Derfor måtte der tys til små pauser i form af "delays". Disse er blevet trimmet, så processen foregår så huritgt som muligt - dog med en sikker margen, så vi ikke kører på grænsen.


Procedure KnapperLaesInd;

Begin

  Knapperlaest[1] := 0;
  Knapperlaest[2] := 0;
  Knapperlaest[3] := 0;

//  writeln('KnapperL?nd . . . ');


  For Knaprow := 1 to AntalKnapStik do begin

//-------  Knap rækker læst en ad gangen. Hvilken række bestemmes af Knaprow.
//-------  Række 1 er tættest på modstande, 4014 og stik til shield.
   for x := AntalKnapStik downto 1 do begin
     if x=Knaprow then digitalwrite(UData,high) else digitalwrite(UData,low);
     delaymicroseconds(44);
     digitalwrite(UCl,HIGH);
     delaymicroseconds(44);
     digitalwrite(UCl,LOW);
     delaymicroseconds(44);
     digitalwrite(UData,low);
     delaymicroseconds(44);
   end;
//--- Strobe sendes for at skrive data ud
   digitalwrite(USTR,HIGH);
   delaymicroseconds(44);
   digitalwrite(USTR,LOW);
   delaymicroseconds(44);
//------ Slut pÃ¥ lÃ

//--- Strobe sendes for at læse data ind
      digitalwrite(ISTR,HIGH);
//     delaymicroseconds(44);
      digitalwrite(ICl,HIGH);
      delaymicroseconds(44);
      digitalwrite(ICl,LOW);
     delaymicroseconds(44);
      digitalwrite(ISTR,LOW);
     delaymicroseconds(44);

      for y:= 1 to 16 do begin
        Knapind[(Knaprow - 1)*16 + y] := digitalread(IData);
        // if digitalread(IData) = 1 then writeln(' Yess ', Knaprow, ' ', Y);
       delaymicroseconds(44);
        digitalwrite(ICl,HIGH);
       delaymicroseconds(44);
        digitalwrite(ICl,LOW);
        delaymicroseconds(44);
      end;

  end;   // For Knaprow := . . .

//  Overfør til inputstak
y:=1;
for x := 1 to AntalKnapper do begin
   if KnapInd[x] = 1 then begin
      KnapperLaest[y]:=x;
      writeln('Yes - ',x);
//      delay(1000);
      inc(y);
   end;
end;

end;
   

procedure indlaesdata;

H


procedure indlaesdata;

Label 1, 99;

{ Indl?knapper fra knapmatrix
Data ekstraheres og l?es i InputStak.
Find ud af, hvilke knapper er trykket
En knap fundet / to knapper fundet
Hvis en knap er fundet, er det en sporskifteknap?
    Ja. Er det optaget/l?? Nej, skift sporet. Ja; ignor?
    Nej, ignor? (N?aussentaster implementeres s?kal dette m?e ?res)
Hvis to knapper fundet, hvilker to knapper er det?
	Begge er sporknapper => Udled spornummer og g?il Findvej.
	Alt andet, ignor? (N?aussentaster implementeres, s?kal dette ?res)

Indl?sporfølere fra Loconet
Hvis positiv, s?eld sporet for optaget/belagt.


  Data, der indl?s fra Loconet via Arduino, som er forbundet med Loconet
  og med RasPi via I2C:
                   OPCode
  Knapper:
            Røde plan	1 - 48
            Gule ranger	49 - 192
            Mellemknapper 193 - 220
            sorte spsk	221 - 348
            Aussentaster 349 - 376
  Signaler:
  Sporskifter:			1051 - 1200
  Følere (fra ServoDecoders):
 
  L?knapper.
   S??e der ikke er l? nogen ind, s??igen.
   Hvis der er l? knapper ind, s?kriv dem over i stak.
   . . .
   1 knap trykket - to knapper trykket - tre knapper trykket
   1 knap: Sporskifter, aussentaster -> videre
   2 knapper: Kørsel eller rangering -> videre
   3 eller flere knapper: Ikke tilladt - afvent ingen knapper trykket.
}


begin

1:
 KnapperLaesInd;
 
 if KnapperTrykket and (Knapperlaest[1] > 0) then goto 99;
 if KnapperTrykket and (Knapperlaest[1] = 0) then begin
     KnapperTrykket := false;
	 Goto 99;
 end;

 // writeln('Knappertrykket = ', KnapperTrykket);
 




 // En knap trykket
//   if (Knapperlaest[1] > 0) and (Knapperlaest[2] = 0) and (Knapperlaest[3] = 0) then begin
// Aussentaster
       if (knapperlaest[2] >= 401) and (knapperlaest[2] <= 432) then begin
	   if (knapperlaest[1] >= 257) and (knapperlaest[1] <= 400) and
              (knapperlaest[2] = 407) then skiftspor(knapperlaest[1]);
      end;
       if (knapperlaest[2] >= 401) and (knapperlaest[2] <= 432) then begin
 	   if (knapperlaest[1] >= 257) and (knapperlaest[1] <= 400) and
               (knapperlaest[2] = 412) then skiftspor(knapperlaest[1]+1);
       end;
       if (knapperlaest[2] >= 401) and (knapperlaest[2] <= 432) then begin
 	   if (knapperlaest[1] >= 257) and (knapperlaest[1] <= 400) and
               (knapperlaest[2] = 413) then skiftspor(knapperlaest[1]);
       end;


// Sporskifter
//   if (knapperlaest[1] >= 257) and (knapperlaest[1] <= 400) then begin
//          writeln(L, ' sorte knapper . . . ');
//          writeln(   ' sorte knapper . . . ');
//          skiftspor(knapperlaest[1]);
//   end;
//   KnapperTrykket := true;
//   goto 99;
//end;






 { Røde knapper }
  If  (knapperlaest[2] <> 0) and (knapperlaest[3] = 0) then begin
      if (knapperlaest[1] >= 1) and (knapperlaest[1] <= 64 ) and (knapperlaest[2] >= 1) and (knapperlaest[2] <= 64) then begin

         writeln(L, ' Røde knapper . . . ');
         writeln(   ' Røde knapper . . . ');
         writeln(L,  'knapperlaest[1] = ', knapperlaest[1],';   knapperlaest[2] = ', knapperlaest[2]);
         writeln(    'knapperlaest[1] = ', knapperlaest[1],';   knapperlaest[2] = ', knapperlaest[2]);

         If odd(knapperlaest[1]) and odd(knapperlaest[2])   then Retning := false;
         If not odd(knapperlaest[1]) and not odd(knapperlaest[2]) then Retning := true;
         If odd(knapperlaest[1]) and not odd(knapperlaest[2]) then begin fejl := 2; goto 99; end;
         If not odd(knapperlaest[1]) and odd(knapperlaest[2]) then begin fejl := 2; goto 99; end;

         Knap1 := Knap[knapperlaest[1]];
         Knap2 := Knap[knapperlaest[2]];

         Koerselstype := Plank;
         writeln(L,  'Knap1 = ', Knap1,';   Knap2 = ', Knap2, ' Kørselstype: ', Koerselstype);
         writeln(L, ' R Retning : ', Retning);
         writeln(    'Knap1 = ', Knap1,';   Knap2 = ', Knap2, ' Kørselstype: ', Koerselstype);
         writeln(   ' R Retning : ', Retning);
         KnapperTrykket := true;
         writeln(L, ' Røde knapper - slut . . . ');
         writeln(   ' Røde knapper - slut. . . ');
         goto 99;
      end;
  end;

{ Gule knapper }
  If  (knapperlaest[2] <> 0) and (knapperlaest[3] = 0) then begin
      if (knapperlaest[1] >= 65) and (knapperlaest[1] <= 224 ) and (knapperlaest[2] >= 65) and (knapperlaest[2] <= 224) then begin

         writeln(L, ' Gule knapper . . . ');
         writeln(   ' Gule knapper . . . ');
         writeln(L,  'knapperlaest[1] = ', knapperlaest[1],';   knapperlaest[2] = ', knapperlaest[2]);
         writeln(    'knapperlaest[1] = ', knapperlaest[1],';   knapperlaest[2] = ', knapperlaest[2]);
         If odd(knapperlaest[1]) and odd(knapperlaest[2])   then Retning := false;
         If not odd(knapperlaest[1]) and not odd(knapperlaest[2]) then Retning := true;
         If odd(knapperlaest[1]) and not odd(knapperlaest[2]) then begin fejl := 2; goto 1; end;
         If not odd(knapperlaest[1]) and odd(knapperlaest[2]) then begin fejl := 2; goto 1; end;

         Knap1 := Knap[knapperlaest[1]];
         Knap2 := Knap[knapperlaest[2]];

         Koerselstype := Rangerk;
         writeln(L, 'Knap1 = ', Knap1,';   Knap2 = ', Knap2, ' Kørselstype: ', Koerselstype, ' G Retning : ', Retning);
         writeln(   'Knap1 = ', Knap1,';   Knap2 = ', Knap2, ' Kørselstype: ', Koerselstype, ' G Retning : ', Retning);
         KnapperTrykket := true;
         writeln(L, ' Gule knapper - slut . . . ');
         writeln(   ' Gule knapper - slut. . . ');
         goto 99;
     end;
  end;


{ Røde knapper og midterknapper}
  If  (knapperlaest[2] <> 0) and (knapperlaest[3] = 0) then begin
     if ((knapperlaest[1] >= 1) and (knapperlaest[1] <= 64) and (knapperlaest[2] >= 225) and (knapperlaest[2] <= 256)) or
         ((knapperlaest[2] >= 1) and (knapperlaest[2] <= 64) and (knapperlaest[1] >= 225) and (knapperlaest[1] <= 256)) then begin

         writeln(L, ' Rød knap incl midterknap . . . ');
         writeln(   ' Rød knap incl midterknap . . . ');

         writeln(L, ' Init : IS1: ', knapperlaest[1],' - IS2: ', knapperlaest[2] );

             If odd(knapperlaest[2])  then Retning := false;
             If not odd(knapperlaest[2])  then Retning := true;

             writeln(L, 'Knapl?ing:  IS1: ', Midterknap[retning, knapperlaest[1]],' IS2: ', Knap[knapperlaest[2]]) ;

             if Knap[knapperlaest[2]] > Midterknap[retning, knapperlaest[1]] then begin
                Knap1 := Midterknap[retning, knapperlaest[1]];
                Knap2 := Knap[knapperlaest[2]];
                writeln(L, ' C : ', Knap1,' - ', Knap2 );
             end else begin
                Knap1 := Knap[knapperlaest[2]];
                Knap2 := Midterknap[retning, knapperlaest[1]];
                writeln(L, ' D : ', Knap1,' - ', Knap2 );
             end;


         Koerselstype := Plank;
         writeln(L,  'Knap1 = ', Knap1,';   Knap2 = ', Knap2, ' Kørselstype: ', Koerselstype);
      end;
      writeln(L, ' Retning : ', Retning);
   KnapperTrykket := true;
   goto 99;
  end;

 { Gule knapper og midterknapper}
  If  (knapperlaest[2] <> 0) and (knapperlaest[3] = 0) then begin
     if ((knapperlaest[1] >= 65) and (knapperlaest[1] <= 224) and (knapperlaest[2] >= 225) and (knapperlaest[2] <= 256)) or
         ((knapperlaest[2] >= 65) and (knapperlaest[2] <= 224) and (knapperlaest[1] >= 225) and (knapperlaest[1] <= 256)) then begin

         writeln(L, ' Rød knap incl midterknap . . . ');
         writeln(   ' Rød knap incl midterknap . . . ');

         writeln(L, ' Init : IS1: ', knapperlaest[1],' - IS2: ', knapperlaest[2] );

             If odd(knapperlaest[2])  then Retning := false;
             If not odd(knapperlaest[2])  then Retning := true;

             writeln(L, 'Knaplæsning:  IS1: ', Midterknap[retning, knapperlaest[1]],' IS2: ', Knap[knapperlaest[2]]) ;

             if Knap[knapperlaest[2]] > Midterknap[retning, knapperlaest[1]] then begin
                Knap1 := Midterknap[retning, knapperlaest[1]];
                Knap2 := Knap[knapperlaest[2]];
                writeln(L, ' C : ', Knap1,' - ', Knap2 );
             end else begin
                Knap1 := Knap[knapperlaest[2]];
                Knap2 := Midterknap[retning, knapperlaest[1]];
                writeln(L, ' D : ', Knap1,' - ', Knap2 );
             end;


         Koerselstype := Plank;
         writeln(L,  'Knap1 = ', Knap1,';   Knap2 = ', Knap2, ' Kørselstype: ', Koerselstype);
      end;
      writeln(L, ' Retning : ', Retning);
    KnapperTrykket := true;
   goto 99;
 end;

99:


//writeln(L, ' Knapper - slut . . . ');
//writeln(   ' Knapper - slut . . . ');
//delay(1000);

end;   {procedure indlaesdata}
   

Function FjernTusind(x: word): word;

Denne funktion fjerner alle cifre i et tal, der er over 999, således at de tre sidste cifre returneres.

I den følgende procedure, FindVej, bruges en lidt speciel teknik til at detektere, hvilke kørselsmuligheder der er i et kryds.


{ Visse tal i sporplan er højere end tusind til at indikere "låste" køreveje
  Disse tusind skal fjernes, så kun selv bloknummeret er tilbage. }

Function FjernTusind(x: word): word;

begin

//x := spor[false, Vejfundet2[0,trin-1], Vejfundet2[1,trin-1]];
FjernTusind := round((x - ( x mod 1000))/1000);  { Tallene over bloknumre, se sporplan  }


end;
   

PROCEDURE findvej;

Denne procedure er nok den "sjoveste" - og en af de mere komplicerede. Man vil steppe sig frem et trin af gangen, indtil man rammer en blindgyde - eller kommer i mål.

På den ene side lyder det simpelt. Men der er nogle forhindringer, man skal tage hensyn til. Synderen i dette puslespil er krydssporene. Der er tre forskellige typer: Et simpelt kryds, hvor man kun kan køre ligeover; et dobbelt kryds, hvor man kan køre i alle fire retninger; og et "halvt" dobbelt kryds, hvor man i den ene retning kan køre to veje - men ikke den anden vej.

Her bliver man nødt til at gøre noget aktivt for at sikre, at programmet nu også kommer med det rigtige resultat til sidst.


PROCEDURE findvej;
    LABEL 1,10,11,12,14,15,19,20,21,22,24,25,29,99;

    VAR   am :  longint;

     BEGIN

{ Vi skal nu til at finde sporvejen. Vi leder kun efter den direkte,
  da omkørsler/overhalinger (umfahrweg) kr?r specialbetjening med UFGT
  og forh?sindstilling af sporskifter.
  Da vi ogs?kal finde sporskifte-stillinger senere, søger vi i begge retninger; b? false og true.
  Begge sporveje skal v? ens !}
  
       for x:=1 to 32 do begin
           Vejfundet1[0,x]:=0;
           Vejfundet1[1,x]:=0;
           Vejfundet2[0,x]:=0;
           Vejfundet2[1,x]:=0;
       end;



      if Knap1 > Knap2 then begin
         x:=Knap1; y:=Knap2;
         Knap1:=y; Knap2:=x;
      end;

       x:=1; y:=1; z:=1;
       trin:=1;

       writeln(L); writeln(L, ' . . . først den ene vej . . . '); writeln(L);
       writeln( ); writeln(   ' . . . først den ene vej . . . '); writeln;

       Vejfundet1[0,1]:=Knap1;
       Vejfundet1[1,1]:=1;      {trin}

       10:
       11:
              writeln(L, ' Trin = ', trin, ' - if trin = 32');
              If trin=32 then begin
                 dec(trin);
                 inc(Vejfundet1[1,trin]);
                 Vejfundet1[0,trin+1]:=0;
                 Vejfundet1[1,trin+1]:=0;                  { Ny }
                 writeln(L, '  11 : Nu:', Vejfundet2[0,trin-1],'  N?e:', Vejfundet2[0,trin], '  trin:', trin);
              end;
       12:
              writeln(L, ' spor[true,Vejfundet1[0,trin],Vejfundet1[1,trin]] = ', spor[true,Vejfundet1[0,trin],Vejfundet1[1,trin]], ' - if = 0');
              If spor[true,Vejfundet1[0,trin],Vejfundet1[1,trin]]=0 then begin
                 dec(trin);
                 if trin=0 then begin fejl:=41; goto 1; end;
                 inc(Vejfundet1[1,trin]);
                 Vejfundet1[0,trin+1]:=0;
                 Vejfundet1[1,trin+1]:=0;
                 writeln(L, '  12,1 : Nu:', Vejfundet1[0,trin-1],'  N?e:', Vejfundet1[0,trin], '  trin:', trin);
                 goto 12;
              end;
              writeln(L, '  Vejfundet1[1,trin] = ', Vejfundet1[1,trin], ' - = 9');
              If Vejfundet1[1,trin]=9 then begin
                 dec(trin);
                 inc(Vejfundet1[1,trin]);
                 Vejfundet1[0,trin+1]:=0;
                 Vejfundet1[1,trin+1]:=0;                  { Ny }
                 writeln(L, '  12,2 : Nu:', Vejfundet1[0,trin-1],'  N?e:', Vejfundet1[0,trin], '  trin:', trin);
                 goto 12;
              end;
              writeln(L, ' Trin = ', trin, ' - if trin = 0');
              If trin=0 then begin fejl:=42; goto 1; end;

               If (spor[true,Vejfundet1[0,trin],Vejfundet1[1,trin]]) = knap2 then begin
                  Vejfundet1[0,trin+1]:=knap2;
                  goto 19;
               end;

               If spor[true,Vejfundet1[0,trin],Vejfundet1[1,trin]] > 1000 then begin
                  writeln(L, ' - - - i loop med > 1000 - - - -');
                  If ((spor[(true),Vejfundet1[0,trin],Vejfundet1[1,trin]] mod 1000)=knap2)
                  and
                     ((Spor[false,Vejfundet1[0,trin],Vejfundet1[1,trin]] mod 1000) = Vejfundet1[0,trin-1])
                  then begin
                     Vejfundet1[0,trin+1]:=knap2;
                     goto 19;
                  end;
               end;

              {>>>>>>>>}
               {Krydsspor problem: Nogle gange kørsel i kun én retning }
              if spor[true,Vejfundet1[0,trin],Vejfundet1[1,trin]] > 1000 then begin
                 ya := FjernTusind( spor[true,Vejfundet1[0,trin],Vejfundet1[1,trin]]);
                 for x := 1 to 4 do begin  { Indtil videre 4 muligheder, nok til Kastdorf  }
                     am := ya mod 10;
                     ya := round((ya - ( ya mod 10))/10);
                     writeln(L, ' 14: am = ',am,', ya = ',ya);
                     writeln(L, Vejfundet1[0,trin-1], ' = ', spor[false,Vejfundet1[0,trin],am] mod 1000,' ? ');
                     if Vejfundet1[0,trin-1] = (spor[false,Vejfundet1[0,trin],am] mod 1000) then goto 14;
                 end;
                 write(L, ' >X>   Trinner sporvalg op : ', Vejfundet1[1,trin], ' inc > ');
                 inc(Vejfundet1[1,trin]);
                 writeln(L, Vejfundet1[1,trin], '  trin=', trin);
                 goto 11;
              end;
              {>>>>>>>>>>>}

        14:    Vejfundet1[0,trin+1]:=spor[true,Vejfundet1[0,trin],Vejfundet1[1,trin]] mod 1000;
               writeln(L, '  14 : Nu:', Vejfundet1[0,trin],'  Næste:', Vejfundet1[0,trin+1], '  trin:', trin);

        15:    inc(trin);
               Vejfundet1[1,trin]:=1;
               writeln(L, '-----------------------------------------------------');
               for x:= 1 to trin do write(L,  Vejfundet1[0,x], ' ');
               writeln(L);
               writeln(L, '-----------------------------------------------------');
               goto 10;

        19:    x:=1; y:=1; z:=1;
                      trin := 1;


        writeln(L); writeln(L, ' . . . og s?en anden vej . . . '); writeln(L);
        writeln( ); writeln(   ' . . . og s?en anden vej . . . '); writeln;

        Vejfundet2[0,1]:=Knap2;
        Vejfundet2[1,1]:=1;      {trin}

        20:
        21:
               writeln(L, ' Trin = ', trin, ' - if trin = 32');
	       If trin=32 then begin
                  dec(trin);                              {  *** DEC sportrin   ***   }
                  inc(Vejfundet2[1,trin]);
                  Vejfundet2[0,trin+1]:=0;
                  Vejfundet2[1,trin+1]:=0;                  { Ny }
                  writeln(L, '  21 : Nu:', Vejfundet2[0,trin-1],'  Næste:', Vejfundet2[0,trin], '  trin:', trin);
               end;
        22:
               writeln(L, ' spor[false,Vejfundet2[0,trin],Vejfundet2[1,trin]] = ', spor[false,Vejfundet2[0,trin],Vejfundet1[1,trin]], ' - if = 0');
               If spor[(false),Vejfundet2[0,trin],Vejfundet2[1,trin]]=0 then begin
                  dec(trin);                              {  *** DEC sportrin   ***   }
                  if trin=0 then begin fejl:=43; goto 1; end;
                  inc(Vejfundet2[1,trin]);
                  Vejfundet2[0,trin+1]:=0;
                  Vejfundet2[1,trin+1]:=0;
                  writeln(L, '  22,1 : Nu:', Vejfundet2[0,trin-1],'  Næste:', Vejfundet2[0,trin], '  trin:', trin);
                  goto 22;
               end;
               writeln(L, '  Vejfundet2[1,trin] = ', Vejfundet2[1,trin], ' - = 9');
               If Vejfundet2[1,trin]=9 then begin
                  dec(trin);                              {  *** DEC sportrin   ***   }
                  inc(Vejfundet2[1,trin]);
                  Vejfundet2[0,trin+1]:=0;
                  Vejfundet2[1,trin+1]:=0;                  { Ny }
                  writeln(L, '  22,2 : Nu:', Vejfundet2[0,trin-1],'  Næste:', Vejfundet2[0,trin], '  trin:', trin);
                  goto 22;
               end;
               writeln(L, ' Trin = ', trin, ' - if trin = 0');
               If trin=0 then begin fejl:=44; goto 1; end;

                 If (spor[(false),Vejfundet2[0,trin],Vejfundet2[1,trin]])=knap1 then begin
                  Vejfundet2[0,trin+1]:=knap1;
                  goto 29;
                 end;

                 If spor[false,Vejfundet2[0,trin],Vejfundet2[1,trin]] > 1000 then begin
                    If ((spor[(false),Vejfundet2[0,trin],Vejfundet2[1,trin]] mod 1000)=knap1)
                    and
                     ((Spor[true,Vejfundet2[0,trin],Vejfundet2[1,trin]] mod 1000) = Vejfundet2[0,trin-1])
                    then begin
                       Vejfundet2[0,trin+1]:=knap1;
                       goto 29;
                    end;
                end;

               {<<<<<<<<<<<<}
               {Krydsspor problem: Nogle gange kørsel i kun én retning }
               if spor[false,Vejfundet2[0,trin],Vejfundet2[1,trin]] > 1000 then begin
                  ya := FjernTusind(spor[false,Vejfundet2[0,trin],Vejfundet2[1,trin]]);
                  for x := 1 to 4 do begin  { Indtil videre 4 muligheder, nok til Kastdorf  }
                      am := ya mod 10;
                      ya := round((ya - ( ya mod 10))/10);
                      writeln(L, ' 14: am = ',am,', ya = ',ya);
                      writeln(L, Vejfundet2[0,trin-1], ' = ', spor[true,Vejfundet2[0,trin],am] mod 1000,' ? ');
                      if Vejfundet2[0,trin-1] = (spor[true,Vejfundet2[0,trin],am] mod 1000) then goto 24;
                  end;
                  write(L, '  ');
                  inc(Vejfundet2[1,trin]);
                  writeln(L, (Vejfundet2[1,trin]), '  trin=', trin);
                  goto 21;
               end;

        24:    Vejfundet2[0,trin+1]:=spor[(false),Vejfundet2[0,trin],Vejfundet2[1,trin]] mod 1000;
               writeln(L, '  24 : Nu:', Vejfundet2[0,trin],'  Næste:', Vejfundet2[0,trin+1], '  trin:', trin);

        25:    inc(trin);
               Vejfundet2[1,trin]:=1;
               writeln(L, '-----------------------------------------------------');
               for x:= 1 to trin do write(L,  Vejfundet2[0,x], ' ');
               writeln(L);
               writeln(L, '-----------------------------------------------------');
               goto 20;

        29:     x:=1; y:=1; z:=1;
                               trin := 1;
1:

   writeln(L);      writeln (L, ' * Fejl ', fejl);
   writeln;         writeln (   ' * Fejl ', fejl);
	  
   for x:= 1 to 20 do begin
       writeln(L, 'Vej fundet: ',  Vejfundet1[0,x],'-', Vejfundet1[1,x],' ',
                                   Vejfundet2[0,x],'-', Vejfundet2[1,x],' ');
       writeln(   'Vej fundet: ',  Vejfundet1[0,x],'-', Vejfundet1[1,x],' ',
                                   Vejfundet2[0,x],'-', Vejfundet2[1,x],' ');
   end;

//   SporstakIkkeLigeLange : Boolean;         SporstakIkkeLigeLange := true;
//   SporstakIkkeEns       : Boolean;         SporstakIkkeEns := true;

x:=1;  y:=0;  z:=0;
xa:=0; ya:=0; za:=0;

// Er de to sporveje lige lange?

      for x:= 1 to 32 do begin
          write(L, 'Lige lange?   Før: ', ' y=', y, ' z=', z);
          if  Vejfundet1[0,x] > 0 then inc(y);
          if  Vejfundet2[0,x] > 0 then inc(z);
          writeln(L, '     Efter: ', ' y=', y, ' z=', z);
      end;

      if (y<>z) then begin

         If y > z then begin   // > Z er den kortere vej
            writeln(L, ' - y > z ');
            for xa := 1 to 32 do Vejfundet1[0,xa] := 0;
            for xa := 1 to z do begin
                Vejfundet1[0,xa] := Vejfundet2[0,z+1-xa];
//              Sporskifter bagefter: !!!
                for ya := 1 to 8 do begin
                    if (Spor[false,Vejfundet2[0,z+1-xa],ya] mod 1000) = Vejfundet2[0,z-xa] then begin
                        Vejfundet1[1,xa] := ya;   // Modulus, fordi tusind-cifret bruges til krydsspor->sporvej
                        writeln(L, '         > ya=',ya);
                    end;
                end;
            end;
         y:=z;
         end;

         If y < z then begin   // < y er den kortere vej
            writeln(L, ' - y < z ');
            for xa := 1 to 32 do Vejfundet2[0,xa] := 0;
            for xa := 1 to z do begin
                Vejfundet2[0,xa] := Vejfundet1[0,y+1-xa];
//              Sporskifter bagefter: !!!
                for ya := 1 to 8 do begin
                    if (Spor[true,Vejfundet1[0,y+1-xa],ya] mod 1000) = Vejfundet1[0,y-xa] then begin
                        Vejfundet2[1,xa] := ya;   // Modulus, fordi tusind-cifret bruges til krydsspor->sporvej
                        writeln(L, '         < ya=',ya);
                    end;
                end;
            end;
         z:=y;
         end;

      end;

    writeln(L ,' Efter Ikke lige lange: ');
    for x:= 1 to 20 do begin
       writeln(L, 'Vej fundet: ',  Vejfundet1[0,x],'-', Vejfundet1[1,x],' ',
                                   Vejfundet2[0,x],'-', Vejfundet2[1,x],' ');
       writeln(   'Vej fundet: ',  Vejfundet1[0,x],'-', Vejfundet1[1,x],' ',
                                   Vejfundet2[0,x],'-', Vejfundet2[1,x],' ');
    end;

//    Stakke er lige lange, men er de ens?

for xa := 1 to y do begin
    ya := ya + Vejfundet1[1,xa];
    za := za + Vejfundet2[1,xa];
end;

writeln(L, ' Lavest er nok kortest (mest lige):   ya=', ya,' za=', za);



//         writeln(L, ' Sammenlign de to stakke: ');
//         writeln(L, Vejfundet1[0,x],'-', Vejfundet2[0,(y+1-x)], ' --- x=', x, ' y+1-x=', y+1-x);
//         Delay (1000);

for x:=1 to y do begin

if ya > za then begin
 writeln(L, 'ya > za');
 Vejfundet1[0,x] := Vejfundet2[0,y+1-x];
//             Sporskifter : !!!
 for yb := 1 to 8 do begin
     writeln(L, Vejfundet1[0,yb], '::', Vejfundet2[0,z-x]);
     if (Spor[true,Vejfundet1[0,x],yb] mod 1000) = Vejfundet2[0,z-x] then  begin
         Vejfundet1[1,x] := yb;   // Modulus, fordi tusind-cifret bruges til krydsspor->sporvej
         writeln(L, '   y=', y, ', z=', z, ', x=', x, ', yb=',yb);
     end;
 end;
end;

if ya < za then begin
 writeln(L, 'ya < za');
 Vejfundet2[0,x] := Vejfundet1[0,z+1-x];
//             Sporskifter : !!!
 for yb := 1 to 8 do begin
     writeln(L, Vejfundet2[0,x], '::', Vejfundet1[0,y-x]);
     if (Spor[false,Vejfundet2[0,x],yb] mod 1000) = Vejfundet1[0,y-x] then begin
        Vejfundet2[1,x] := yb;   // Modulus, fordi tusind-cifret bruges til krydsspor->sporvej
        writeln(L, '   y=', y, ', z=', z, ', x=', x, ', yb=',yb);
        end;
    end;
 end;
end;

writeln(L, 'Efter korrigering: ');
for x:= 1 to 20 do begin
    writeln(L, 'Vej fundet: ',  Vejfundet1[0,x],'-', Vejfundet1[1,x],' ',
                                Vejfundet2[0,x],'-', Vejfundet2[1,x],' ');
    writeln(   'Vej fundet: ',  Vejfundet1[0,x],'-', Vejfundet1[1,x],' ',
                                Vejfundet2[0,x],'-', Vejfundet2[1,x],' ');
end;


99:

END;  {Findvej}



PROCEDURE checkspor;

K


PROCEDURE checkspor;

LABEL 99;

    BEGIN

{ Der checkes , om begge spor er frie, og om begge spor er besatte }

     x:=1; y:=1; z:=1;
	 writeln(' . . . check spor . . . ');

{Vi undersøger, om den fundne vejs spor er optaget eller ej}
       for z:=1 to 32 do begin                { Trin i Sporskema }
          for x:=1 to 16 do begin            { Sporskemanr }
             for y:=1 to 32 do begin          { Trin i de andre staks }
                if Vejfundet1[0,z]=0 then goto 99; { Hop ud af l›kken pga "f‘rdig" }
                if Sporskema[x,y]=Vejfundet1[0,z] then begin
                   fejl:=7;   goto 99;
                end;
             end;
          end;
       end;



99:


END;
  

PROCEDURE findsporskifter;

L


PROCEDURE findsporskifter;

BEGIN
 Writeln(L);   Writeln(L, 'Findsporskifter:');
 Writeln();    Writeln(   'Findsporskifter:');

{ Nulstilling }
   for x:=1 to 32 do sporskifterfundet1[x]:=0;
   for x:=1 to 32 do sporskifterfundet2[x]:=0;

{Vi indl?r data fra sporskiftemmatrixen: (form: XX XX XX XX XX XX XX XX )}

   for x:=1 to 32 do begin
       if Vejfundet1[0,x] > 0 then
       sporskifterfundet1[x]:=Weiche[true, Vejfundet1[0,x], Vejfundet1[1,x]];

{       if Vejfundet1[0,x] = 0 then
       sporskifterfundet1[x-1]:=Weiche[retning, Vejfundet1[0,x], Vejfundet1[1,x]];
 }
       if Vejfundet2[0,x] > 0 then
       sporskifterfundet2[x]:=Weiche[false, Vejfundet2[0,x], Vejfundet2[1,x]];

{       if Vejfundet2[0,x] = 0 then
       sporskifterfundet2[x-1]:=Weiche[not retning, Vejfundet2[0,x], Vejfundet2[1,x]];
 }

       writeln(L, ' 1: ', Vejfundet1[0,x],' ', sporskifterfundet1[x], ' - 2: ',    Vejfundet2[0,x],' ', sporskifterfundet2[x]);
       writeln(   ' 1: ', Vejfundet1[0,x],' ', sporskifterfundet1[x], ' - 2: ',    Vejfundet2[0,x],' ', sporskifterfundet2[x]);

   end;

 { De to stakke kombineres til en enkelt: }
     for x:= 1 to 32 do begin
         for y := 1 to 32 do begin
             if     (vejfundet1[0,x] = vejfundet2[0,y])
 			   and (vejfundet1[0,x] > 0)
 			   and (vejfundet2[0,y] > 0) then begin
                write(L, 'Før:  sporskifterfundet1[', x, '] =', sporskifterfundet1[x], ',sporskifterfundet2[', y, '] =', sporskifterfundet2[y]);
                sporskifterfundet1[x] := (sporskifterfundet1[x] OR sporskifterfundet2[y]);
                sporskifterfundet2[y] := sporskifterfundet1[x];
                writeln(L, '  ::  Eft:  sporskifterfundet1[', x, '] =', sporskifterfundet1[x], ',sporskifterfundet2[', y, '] =', sporskifterfundet2[y]);
             end;
         end;
     end;

END;
   

procedure vejfundet_til_Sporskema;

M


procedure vejfundet_til_Sporskema;

       { Nu har vi en stak med en kørselsvej. Denne skal nu l?es over i }
       { Sporskemaken efter de tal, der er der i forvejen.                 }

{        Data fra vejfundet l?es s?ver i Sporskema.
         Det samme med sporskifter                       }

BEGIN

    writeln(L, ' . . . vejfundet_til_Sporskema . . . ');

       x:=0;
       repeat x:=x+1 until Sporskema[x,1]=0;
       Sporskemanr:=x;
       for x:=1 to 32 do Sporskema[Sporskemanr,x]:=Vejfundet1[0,x];
       RetningSPST[Sporskemanr] := Retning;

	   Knap1 := 0;
	   Knap2 := 0;

END;
   

procedure Sporskifter_til_sporskifteskema_og_SpskStakFIFO;

N


procedure Sporskifter_til_sporskifteskema_og_SpskStakFIFO;

BEGIN

    writeln(L, ' . . . Sporskifter_til_sporskifteskema_og_SpskStakFIFO . . . ');

{Først overførsel til almindelig stak sammenhørende med sporskema}

  for x := 1 to 32 do begin
      write(L, '   sporskifterfundet1[', x, ']=', sporskifterfundet1[x], '  >>>   ');
      sporskifteskema[sporskemanr, x] := sporskifterfundet1[x];
      writeln(L, '   sporskifteskema[sporskemanr, ', x, ']=', sporskifteskema[sporskemanr, x]);
  end;

{Herefter overførsel til FIFOstak, hvor sporskifterne blivet l? ud, s?e kan skiftes }
{Overs?else fra spor/sporskifte til Loconet adresse inklusive}
{DIRection = lige ud = Closed = 1 }
{          = afvig   = thrown = 0 }
{ Se mere i regneark under knapper nederst  }

for x := 1 to 32 do begin
    if sporskifteskema[sporskemanr, x] > 0 then begin
        y:= sporskifteskema[sporskemanr, x];

//  Der skal "filtreres" bedre: Kun de spor, der virkelig skal skiftes, bliver sat til a skifte
//  Nu tages alle sporskifter i kørevej og bliver skiftet
        for z := 1 to 8 do begin
          if (y) > 0 then begin
//	  if (y and $3) > 0 then begin
             Spsk_Adresse := LNWeiche[sporskema[sporskemanr, x], z] ;
             writeln(L, '  y=', y, '   Spsk_Adresse = ', Spsk_Adresse, '   Sporskiftestilling[Spsk_Adresse]=', Sporskiftestilling[Spsk_Adresse]);
             // Sporskiftestilling false/true :: y and $3   =>  false=02 ; true=01
             if Sporskiftestilling[Spsk_Adresse] <> (y and $3) then begin
                   if y and $3 = 1 then begin Spsk_DIRetning := 1;  Spsk_ONoutput  := 1;   SpskStakFIFOPUSH; end;
                   if y and $3 = 2 then begin Spsk_DIRetning := 0;  Spsk_ONoutput  := 1;   SpskStakFIFOPUSH; end;
                   if y and $3 = 0 then delay(1);   //Hvis y = 0 s?kal sporskiftet ikke skiftes og derfor springes over.
             end else begin

                for xa := 1 to 16 do begin
                    for ya := 1 to 32 do begin
                      if WeicheLN[Spsk_Adresse,0] = Sporskema[xa,ya] then
                         sporskifteskema[xa,ya] := sporskifteskema[xa,ya] and (not ( 3 shl (WeicheLN[Spsk_Adresse,1]*2 - 2)));
                    end;
                end;

             end;
             y := y shr 2;
	  end;
        end;
   end;

end;
end;        // Procedure Sporskifter_til_sporskifteskema_og_SpskStakFIFO
  

Procedure UpCode_B0;

O


Procedure UpCode_B0;   { Request switch function }
 var
  Adresse1, Adresse2, UpCode1, CheckSum : longint;
  err : integer;
begin

{P4: checksum test !! }

 Val('$'+PI[1], UpCode1, err);
  Val('$'+PI[2], Adresse1, err);
   Val('$'+PI[3], Adresse2, err);
    Val('$'+PI[4], CheckSum, err);

  if (UpCode1 xor Adresse1 xor Adresse2 xor CheckSum) = $FF then begin

  Spsk_ONoutput  := (Adresse2 and $10) shr 4;
  Spsk_DIRetning := (Adresse2 and $20) shr 5;

  Adresse2 := ((Adresse2 and $F) shl 7);
  Adresse := Adresse1 + Adresse2 + 1;
  writeln(L, ' B0: ', Adresse, '  ON=', Spsk_ONoutput, '  DIR=', Spsk_DIRetning);
  end
  else
      writeln(L, ' B0 Checksum Error !!!');

end;
   

Procedure UpCode_B1;

P


Procedure UpCode_B1;   { Turnout sensor state report  }
Label 99;

 var
  Adresse1, Adresse2, UpCode1, CheckSum : longint;
  err : integer;
begin

{P4: checksum test !! }

Val(HexB(Ord(PI[1])), UpCode1, err);
Val(HexB(Ord(PI[2])), Adresse1, err);
Val(HexB(Ord(PI[3])), Adresse2, err);
Val(HexB(Ord(PI[4])), CheckSum, err);
        writeln();
        writeln(L, 'B1 start -----------------------------------------------');
    	writeln(L, 'B1:  Val-> ', UpCode1,' ', Adresse1,' ', Adresse2,' ', CheckSum);
    	writeln(   'B1:  Val-> ', UpCode1,' ', Adresse1,' ', Adresse2,' ', CheckSum);

  if (UpCode1 xor Adresse1 xor Adresse2 xor CheckSum) = $FF then begin
      Blok_SensorLevel := (Adresse2 and $10) shr 4;  { Sensor level - low/high }
      Blok_InputSource := (Adresse2 and $20) shr 5;  { Input source - DS54 / switch }

      Adresse2 := (Adresse2 and $F) shl 7;
      Adresse := Adresse1 + Adresse2 + 1;

      writeln(L, ' Modtaget B1: ', Adresse, '  SL=', Blok_SensorLevel, '  IS=', Blok_InputSource);


     if Blok_SensorLevel = 1 then begin sporskiftestilling[Adresse] := 1;  LEDStilling := 1; end;
     if Blok_SensorLevel = 0 then begin sporskiftestilling[Adresse] := 2;  LEDStilling := 2; end;

// Send stilling til LEDs
      LEDSpSk[1] := chr(1);
      LEDSpSk[2] := chr(Adresse-1050);
      LEDSpSk[3] := chr(LEDStilling);
      sleep(50);
      try
        fpwrite(handleTL, LEDSpSk, 4);
        writeln('Writing spsk . . . ', LEDSpSk[1]);
      except
        writeln('Error writing');
        halt;
      end; //try
      sleep(50);


   end
  else
      writeln(L, ' B1 Checksum Error !!!');


  writeln(L, 'Adresse=', Adresse, '  sporskiftestilling[Adresse]=', sporskiftestilling[Adresse]);

99:
writeln(L, ' B1 Slut . . . ----------------------------');
end;
   

Procedure UpCode_B2;

Q


Procedure UpCode_B2;   { General sensor input codes   }
 var
  Adresse1, Adresse2, UpCode1, CheckSum : longint;
  err : integer;

 begin

{P4: checksum test !! }

 Val(HexB(Ord(PI[1])), UpCode1, err);
 Val(HexB(Ord(PI[2])), Adresse1, err);
 Val(HexB(Ord(PI[3])), Adresse2, err);
 Val(HexB(Ord(PI[4])), CheckSum, err);
     	writeln( ' Val-> ', UpCode1,' ', Adresse1,' ', Adresse2,' ', CheckSum);
     	writeln(     ' Val-> ', UpCode1,' ', Adresse1,' ', Adresse2,' ', CheckSum);

  if (UpCode1 xor Adresse1 xor Adresse2 xor CheckSum) = $FF then begin

  Blok_SensorLevel := (Adresse2 and $10) shr 4;  {Sensor level - low high}
  Blok_InputSource := (Adresse2 and $20) shr 5;  {Input source - DS54 switch. I Bostrøms = Bit 0 i adresse?}
  Xcb := (Adresse2 and $20) shr 6; {control bit - reserved for future use }

  Adresse2 := ((Adresse2 and $F) shl 7);
  Adresse := ((Adresse1 + Adresse2) shl 1) + Blok_InputSource + 1;
  writeln(L, ' B2: ', Adresse, '  SL=', Blok_SensorLevel, '  IS=', Blok_InputSource);
   end
  else
      writeln(L, ' B2 Checksum Error !!!');

end;
   

Procedure UpCode_B4;

R


Procedure UpCode_B4;   { Long acknowledge  }
 var
  Adresse1, Adresse2, UpCode1, CheckSum : longint;
  err : integer;

  begin

{P4: checksum test !! }

  Val(HexB(Ord(PI[1])), UpCode1, err);
  Val(HexB(Ord(PI[2])), Adresse1, err);
  Val(HexB(Ord(PI[3])), Adresse2, err);
  Val(HexB(Ord(PI[4])), CheckSum, err);
      	writeln(' Val-> ', UpCode1,' ', Adresse1,' ', Adresse2,' ', CheckSum);
      	writeln(     ' Val-> ', UpCode1,' ', Adresse1,' ', Adresse2,' ', CheckSum);

  if (UpCode1 xor Adresse1 xor Adresse2 xor CheckSum) = $FF then begin

  writeln(L, ' B4: Copy of OP_Code=', PI[2], '  ACK1=', PI[3]);
  end
  else
      writeln(L, ' B4 Checksum Error !!!');

end;
   

PROCEDURE LNRead;

S


PROCEDURE LNRead;

begin

{ I2C}

PI[1] :=chr(ord('1') - ord('0'));

  try
    fpwrite(handleLN, PI, 1);
  except
     writeln('Error writing');
     halt;
  end; //try
  sleep(50);

PI[1] := #99;

try
  fpread(handleLN, PI, 4);
except
  writeln('Error reading');
  halt;
end;
sleep(50);

//I2C

//writeln(' ReadLN: 1=',HexB(Ord(PI[1])),' 2=',HexB(Ord(PI[2])),' 3=',HexB(Ord(PI[3])),' 4=',HexB(Ord(PI[4])),' ');
//writeln(' ReadLN: 1=',PI[1],' 2=',PI[2],' 3=',PI[3],' 4=',PI[4],' ');
// delay(1000);

if OpCodeinput > '' then begin

 //For test:
//      writeln(L, ' Init OpCode Input: ', OpcodeInput);

       //if HexB(Ord(PI[1])) = 'B0' then UpCode_B0; { Sende }
       if HexB(Ord(PI[1])) = '$B1' then UpCode_B1; { Modtage }
       //if HexB(Ord(PI[1])) = 'B2' then UpCode_B2; { Sende/Modtage }
       //if HexB(Ord(PI[1])) = 'B4' then UpCode_B4;

       { Sporskifter fjernes fra sporskifteskema, når det er skiftet (ack modtaget)}

       if HexB(Ord(PI[1])) = '$B1' then begin
          for x := 1 to 16 do begin
              for y := 1 to 32 do begin
                  if WeicheLN[Adresse,0] = Sporskema[x,y] then begin
                     sporskifteskema[x,y] := sporskifteskema[x,y] and (not ( 3 shl (WeicheLN[Adresse,1]*2 - 2)));
//                     Writeln(L, 'sporskifteskema[x,y]=', sporskifteskema[x,y]);
//                     Writeln(L, 'WeicheLN[Adresse,1]=', WeicheLN[Adresse,1]);
//                     Writeln(L, 'WeicheLN[Adresse,1]*2=', (WeicheLN[Adresse,1]*2));
//                     Writeln(L, 'WeicheLN[Adresse,1]*2 - 2=', ((WeicheLN[Adresse,1]*2) - 2));
//                     Writeln(L, '3 shl (WeicheLN[Adresse,1]*2=', 3 shl (WeicheLN[Adresse,1]*2));
//                     Writeln(L, '3 shl (WeicheLN[Adresse,1]*2 - 2=', (3 shl (WeicheLN[Adresse,1]*2 - 2)));
//                     Writeln(  'sporskifteskema[x,y]=', sporskifteskema[x,y]);
//                     Writeln(  'WeicheLN[Adresse,1]=', WeicheLN[Adresse,1]);
//                     Writeln(  'WeicheLN[Adresse,1]*2=', (WeicheLN[Adresse,1]*2));
//                     Writeln(  'WeicheLN[Adresse,1]*2 - 2=', ((WeicheLN[Adresse,1]*2) - 2));
//                     Writeln(  '3 shl (WeicheLN[Adresse,1]*2=', 3 shl (WeicheLN[Adresse,1]*2));
//                     Writeln(  '3 shl (WeicheLN[Adresse,1]*2 - 2=', (3 shl (WeicheLN[Adresse,1]*2 - 2)));
                  end;
              end;
          end;
       end;

end;
Delay(1);
end;
   

Procedure toemsporstak;

T


Procedure toemsporstak;
Label 1;

{ Tømmer sporstakke, når alle  sporskifter er skiftet }
{ Hvis sporskifteskema blok er tom, så nulstilles samme søjle fra sporskema
  - midlertidigt, indtil sporføling er implementeret}
{ Når sporføling er implementeret, skal der oprettes en stak til de(t) spor,
  hvor toget kører til. Blokken flyttes fra Sporskema til denne stak, således
  at Sporskema tømmes. }
Begin
//  writeln(L, ' Tømmer sporstak . . . ');
//  writeln(' Tømmer sporstak . . . ');
   for x := 1 to 16 do begin
       for y := 1 to 32 do begin
           if sporskifteskema[x,y] > 0 then goto 1;
           if y = 32 then begin
              for z := 1 to 32 do sporskema[x,z] := 0;
           end;
       end;
   end;

1:
end;
   

PROCEDURE udskrivskema;

U


PROCEDURE udskrivskema;
    BEGIN
    clrscr;
     writeln(L, 'CAP   1    2    3    4    5    6    7    8    9    10   11   12   13   14   15   16');
     writeln(L, '-----------------------------------------------------------------------------------');
        FOR x:=1 to 20 do begin
	  write(L, x:2,' :');
          FOR y:=1 to 16 DO write(L,' ',sporskema[y,x]:3,' ');
          writeln(L);
        END;
    write(L, '      '); FOR y:=1 to 16 DO begin
			if RetningSPST[y]= false then write(L, ' <-  ');
			if RetningSPST[y]= true  then write(L, ' ->  ');
		   end;
    writeln(L);

    if fejl>0 then writeln(L, 'Fejlnr. ',fejl)
    else writeln(L, '                               ');

    END;   {Udskriv stakke  }
   

PROCEDURE udskrivSPSKskema;

V


 PROCEDURE udskrivSPSKskema;
    BEGIN
     {clrscr;}
     writeln( L, 'SPSK  1    2    3    4    5    6    7    8    9    10   11   12   13   14   15   16');
     writeln( L, '-----------------------------------------------------------------------------------');
        FOR x:=1 to 20 do begin
	  write(L, x:2,' :');
          FOR y:=1 to 16 DO write(L, ' ',sporskifteskema[y,x]:3,' ');
          writeln(L);
        END;
     writeln(L);

    if fejl>0 then writeln( 'Fejlnr. ',fejl)
    else writeln(L, '                               ');

END;   {Udskriv sporskifte stakke  }
   

PROCEDURE udskrivSpskStakFIFO;

W


PROCEDURE udskrivSpskStakFIFO;

begin
        clrscr;
        for x:= 1 to 40 do begin
            write(L, ' SpskStakFIFO ', x);
            for y:= 1 to 3 do write(L, ' : ' , SpskStakFIFO[x,y]);
            writeln(L);

        end;

end;   {Udskriv sporskifte FIFO stak  }
   

PROCEDURE udskrivSpSk;

X


PROCEDURE udskrivSpSk;

begin
    clrscr;
   // gotoxy(1,1);

    for x:=1051 to 1174 do begin

        if sporskiftestilling[x] = 2 then write('/');
        if sporskiftestilling[x] = 1  then write('-');
        if x mod 5 = 0 then write(' ');
        if x mod 20 = 0 then begin write(' '); writeln; end;

    end;
    writeln;
end;
   

PROCEDURE SletteStakke;

Y


PROCEDURE SletteStakke;

begin

FOR x:=1 to 32 do begin
  FOR y:=1 to 16 DO Begin
      sporskema[y,x] := 0;
      sporskifteskema[y,x] := 0;
 END;
   writeln(' Stakke  slettet!');
end;   

Hoved program

Z


//  Hovedprogram -----


Begin

Logdate := 'today';
assign(L, 'Log-'+Logdate+'.txt'); Rewrite(L);

init;

Clrscr;
  writeln('Ready to work . . . ');
  writeln(L, 'Ready to work . . . ');

Repeat

(* Kald procedure/funktion *)

Indlaesdata;

// writeln('Knap1 = ', Knap1, ';   Knap2 = ', Knap2, '; Knappertrykket ', Knappertrykket);

if (Knap1 > 0) and (Knap2 > 0) then begin
// if (Knap1 > 0) and (Knap2 > 0) and (not Knappertrykket) then begin
                writeln('Findvej =>');
		Findvej;
                writeln('Checkspor =>');
		Checkspor;
		If fejl = 0 then findsporskifter;
		If fejl = 0 then Vejfundet_til_Sporskema;
                udskrivskema;
		If fejl = 0 then Sporskifter_til_sporskifteskema_og_SpskStakFIFO;
                udskrivSPSKskema;
                Delay(1000);
end;

if fejl > 0 then begin
   writeln(' I Repeat loop: Fejl : ', Fejl);
      fejl := 0;
      Knap1 := 0;
      Knap2 := 0;
   end;

{ StilAlt; } 

SpskStakFIFOPOP;    {Skriv til Loconet fra Sporskifte FIFO stak }

LNRead;

toemsporstak;

(* Kald slut *)

//udskrivSpSk;

(* Pr‘senter resultat *)
 {
Clrscr;
udskrivskema;

udskrivSPSKskema;

}

(* Pr‘sentation slut   *)


if keypressed then KBValg1 := readkey;

if KBValg1 = 'a' then begin
   clrscr;
   udskrivskema;
        sleep(1000);
   KBValg1 := '0';
end;
if KBValg1 = 'z' then begin
   clrscr;
   udskrivSPSKskema;
        sleep(1000);
   KBValg1 := '0';
end;
if KBValg1 = 's' then begin
   clrscr;
   udskrivSpskStakFIFO;
        sleep(1000);
   KBValg1 := '0';
end;
if KBValg1 = 'd' then begin
   clrscr;
   SletteStakke;
        sleep(1000);
   KBValg1 := '0';
end;
if KBValg1 = 't' then begin

   writeln('Testing skema valg med test udskrift . . . ');
        sleep(5000);
   KBValg1 := '0';
end;

 until KBValg1 = 'q';

Close(L);

{Test: sporskiftestilling stak  }
assign(F, 'Sporskiftestilling-luk.txt');
Rewrite(F);

for x := 1051 to 1174 do writeln(F, x,'  ',Sporskiftestilling[x]);
Close(F);

end.   

Alt ialt



Z


DHTML Menu By Milonic JavaScript