FUNCTION_BLOCK "FB_RearrangeStartCoordination"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      xInReset : Bool;
      xInRearrangeStartDelay : Time;
   END_VAR

   VAR_IN_OUT 
      udt_InOutStorageSite : "udt_StorageSite";
   END_VAR

   VAR 
      arrbMarkLatch : Array[1..12] of Bool;
      arrtonUmlStart {InstructionName := 'TON_TIME'; LibVersion := '1.0'; S7_SetPoint := 'False'} : Array[1..12] of TON_TIME;
      nLagerIndex { S7_SetPoint := 'True'} : Int;
      nblkId : Int;
   END_VAR


BEGIN
	// -------- Reset ----------
	IF #xInReset THEN
	    FOR #nLagerIndex := 1 TO 12 DO
	        #arrbMarkLatch[#nLagerIndex] := FALSE;
	        #arrtonUmlStart[#nLagerIndex](IN := FALSE,
	                                   PT := #xInRearrangeStartDelay);
	        #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageCtrl.xMarkPulse := FALSE;
	        // keine Requests offen lassen ??
	        // #udt_InOutStorageSite.arrudt_Storage[nLagerIndex].udt_RearrangeStorageCtrl.xRearrangeRequest := FALSE;
	    END_FOR;
	END_IF;
	
	
	
	// -------- Hauptlogik pro Lager ----------
	FOR #nLagerIndex := 1 TO 12 DO
	    
	    // erstes Mark-Telegramm "fangen"
	    IF #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageCtrl.xMarkPulse AND (NOT #arrbMarkLatch[#nLagerIndex]) THEN
	        // Nur starten, wenn Lager gerade nichts anderes tut
	        IF (NOT #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageState.xRearrangeBusy)
	            AND (NOT #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageState.xRearrangeGrant)
	            AND (NOT #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageState.xRemoveBusy)
	            AND (NOT #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageState.xRemoveGrant)
	            AND (NOT #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageState.xEmptyBusy) THEN
	            #arrbMarkLatch[#nLagerIndex] := TRUE;      // Zeitfenster scharf schalten
	        END_IF;
	    END_IF;
	    
	    // MarkPulse verbrauchen (1-Zyklus-Impuls)
	    #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageCtrl.xMarkPulse := FALSE;
	    
	    //TON läuft, solange Latch aktiv
	    #arrtonUmlStart[#nLagerIndex](IN := #arrbMarkLatch[#nLagerIndex],
	                               PT := #xInRearrangeStartDelay);
	    
	    // Wenn Wartezeit abgelaufen: Umlagern anfordern (UmlReq setzen)
	    IF #arrtonUmlStart[#nLagerIndex].Q THEN
	        #nblkId := #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageCtrl.nBlockID;
	        IF (#nblkId >= 1) AND (#nblkId <= 3) AND #udt_InOutStorageSite.arrudt_BlockGroup[#nblkId].udt_BlockGroupCtrl.xReadyRearrange THEN
	            // Interlocks (keine Kollision mit Aus-/Empty)
	            IF (NOT #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageState.xRemoveBusy)
	                AND (NOT #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageState.xRemoveGrant)
	                AND (NOT #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageState.xEmptyBusy) THEN
	                #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageCtrl.xRearrangeRequest := TRUE;   // bleibt TRUE bis angenommen
	            END_IF;
	        END_IF;
	    END_IF;
	    
	    // Wenn Unterlogik angenommen hat (Uml_Busy=TRUE), Fenster schließen
	    IF #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageState.xRearrangeBusy THEN
	        #arrbMarkLatch[#nLagerIndex] := FALSE;      // TON fällt ab
	        // Request kann (muss nicht) zurückgenommen werden – ich empfehle:
	        #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageCtrl.xRearrangeRequest := FALSE;
	    END_IF;
	    
	    // Sicherheit: Nach Done definitiv Latch/Req aus
	    // IF #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageState.xRearrange_Done THEN
	    //     #arrbMarkLatch[#nLagerIndex] := FALSE;
	    //     #udt_InOutStorageSite.arrudt_Storage[#nLagerIndex].udt_RearrangeStorageCtrl.xRearrangeRequest := FALSE;
	    // END_IF;
	    
	END_FOR;
END_FUNCTION_BLOCK

