Compare commits

...

2 Commits

+139
View File
@@ -0,0 +1,139 @@
FUNCTION "LP_Ziel_FC" : Void
TITLE = Ziel-FC: LeerPuffer_OmniFahren
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : AE
FAMILY : Module
NAME : Ziel
//SCL-Portierung des AWL-Bausteins FC5181 "LP_Ziel_FC" (verhaltensgleich).
//
//Der Baustein hatte im AWL-Original die Bausteineigenschaft "Parameterversorgung
//ueber Register" (ParameterPassing) aktiv und wurde per "UC FC[..]" indirekt aus
//AWL aufgerufen -> aus SCL nicht compilierbar. Er liest ausschliesslich globale
//Merker (MW190 = Schleusen-Nr) sowie den Bool-Merker "MB3305" und ruft die
//Zielbausteine voll qualifiziert auf -> keine echte Registerabhaengigkeit.
//Als SCL-Baustein entfaellt die Option und er ist direkt aus SCL aufrufbar
//(CASE 5181 in MHMOmniSchleuse).
//
//Der indirekte Dispatch (AWL: "L MW190 / L 3305 / NE_I / JC X3305E") ist als CASE
//ueber die Schleusen-Nr (MW190) ausgefuehrt. Es existiert nur der Zweig 3305; ein
//AWL-BEU/BEC im getroffenen Zweig ist als RETURN bzw. "IF <RLO> THEN RETURN;"
//umgesetzt (verhaltensgleich, da nach dem Dispatch nur noch das Bausteinende folgt).
//Die Merker-Schnittstelle (MW190 vom Aufrufer, M180.6 = Weiterfahrt-Freigabe,
//MB199 = DatenOut-Rueckmeldung) bleibt erhalten.
//
//ABWEICHUNGEN ZUM AWL-ORIGINAL (bei Inbetriebnahme pruefen!):
// - DatenOut: der Merker-Scratch-Bereich M220 (Such-/OutDaten-Pointer P#M220.0)
// ist durch den lokalen Puffer #DatenPuffer ersetzt (SEARCHDATEN/OUTDATEN sind
// VARIANT statt POINTER). MW220/MW224/MW226 werden dadurch NICHT mehr als
// Merker beschrieben/gelesen (Ergebnis identisch, keine Merker-Nebenwirkung).
// Lager-DB = Datensatz-Wort 2 (=M224), Lager-DW = Wort 3 (=M226).
// - BTI (BCD-Wort -> Int, "Damit Int 1-10 als Ziel") ist ueber den Projekt-FC
// "BCD (4stellig)_to_INT" ausgefuehrt; Fehlerverhalten bei ungueltiger BCD kann
// abweichen (BTI setzt BIE).
// - Indirekter DB-Zugriff (AWL: OPEN_DB DB[Lager_DB] / A DBX[AR1Zeiger] mit
// Pointer-Arithmetik ADD DINT#70 / SLD 3 / OD 7) ist durch PEEK_BOOL
// (area 16#84, byteOffset = Lager_DW+70, bitOffset = 7 -> Bit 7: Inilauf)
// ersetzt. Die Temp "AR1Zeiger" wird dadurch nicht mehr benoetigt.
// - AWL "CLR / S M180.6": die Set-Operation steht unter RLO=0 (CLR) und wird
// daher NICHT ausgefuehrt (bewusst deaktiviert; Weiterfahrt wird ueber
// MSorterRein FB5423/5 gestartet). M180.6 bleibt an dieser Stelle unveraendert.
// - "MB3305" wird (wie im AWL: A / BEC) als Bool-Symbol behandelt.
// - Word-Vergleiche direkt (z.B. (Ziel_hex AND W#16#F000) = W#16#A000);
// MW190 wird fuer den CASE ueber WORD_TO_INT in Int gewandelt.
// - Zusaetzliche Temp "DatenPuffer" (Array[0..15] of Word, nicht im XML-Interface)
// als DatenOut-Puffer eingefuehrt. TypedConstants DINT#70/DINT#1/DINT#0 1:1.
// - "Default_Ziel"/"Rec_DEST_Ziel" werden als Int beschrieben (AWL: 16-Bit-T von
// Ziel_int); falls die DB-Member als Word deklariert sind -> INT_TO_WORD noetig.
VAR_TEMP
Ziel_hex : Word;
Ziel_int : Int;
Zielebene : Word;
Error : Byte;
Position : Int;
Lager_DB : Int;
Lager_DW : Int;
AR1Zeiger : DWord; // Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)
AR1Start : DInt; // Startwert mit Offset 0
SSDW : Int;
EndZiel : Word;
Variante : Int;
AbrufID : DInt;
Fahrlisten_TrolleyID : DInt;
Fahrlisten_AbrufID : DInt;
Fahrlisten_Lager : Int;
Trolley_unbekannt : Bool; // Trolley ist nicht in DL
Express_Abruf : Bool;
DatenPuffer : Array[0..15] of Word; // Puffer fuer DatenOut (ersetzt Merker-Scratch M220)
END_VAR
BEGIN
// NW1: Rueckmeldung - Rueckmeldungen erst mal resetten
"M180.6" := FALSE; // Weiterfahrt von Ziel-FC erlaubt
// NW2: Schleuse 3305: Weiterfahren erlaubt ? (Sorter LP)
// AWL: L MW190 / L 3305 / NE_I / JC X3305E (Aufruf von Schleuse 3305?)
CASE WORD_TO_INT("MW190") OF
3305:
IF "MB3305" THEN
RETURN; // AWL: A MB3305 / BEC
END_IF;
// Leer-Puffer ermitteln:
"Leerpuffer to Rein-Lager ermitteln"(Puffer => "Ziel_hex");
// Ziel = Leer-Lager?
IF ("Ziel_hex" AND W#16#F000) <> W#16#A000 THEN // (AWL: AW F000 / EQ_I A000 / JC LagerOk / BEU)
RETURN; // Kein Lager frei!
END_IF;
// AWL: L Ziel_hex / L W#16#FF / AW / BTI / T Ziel_int (Damit Int 1-10 als Ziel!)
"BCD (4stellig)_to_INT"(BCD_Wert := ("Ziel_hex" AND W#16#00FF),
Int_Wert => "Ziel_int");
// Check, ob Ziel-Lager Inilauf aktiv hat:
#DatenPuffer[0] := INT_TO_WORD("Ziel_int"); // Suchschluessel (AWL: T MW220)
"DatenOut"(SSDB := 275,
SSDW := 0,
PARA := W#16#0000, // Eintrag lesen
SEARCHDATEN := #DatenPuffer,
RE_VAL => "MB199",
Position => #Position,
OUTDATEN := #DatenPuffer);
// AWL: L MB199 / L 2#1111111 / AW / L 0 / NE_I / JC Egal (Bit 7 ausblenden; Fehler vorhanden?)
IF BYTE_TO_INT("MB199" AND B#16#7F) = 0 THEN // kein Fehler -> Inilauf pruefen
"Lager_DB" := WORD_TO_INT(#DatenPuffer[2]); // AWL: L MW224 / T Lager_DB
"Lager_DW" := WORD_TO_INT(#DatenPuffer[3]); // AWL: L MW226 / T Lager_DW
"AR1Start" := INT_TO_DINT("Lager_DW"); // Startwert mit Offset 0
// AWL: ADD DINT#70 / SLD 3 / OD 7 -> Bit-Pointer auf DBX(Lager_DW+70).7 (Bit 7: Inilauf)
IF PEEK_BOOL(area := 16#84,
dbNumber := INT_TO_DINT("Lager_DB"), // Lager-DB
byteOffset := "AR1Start" + DINT#70, // Offset Status
bitOffset := 7) THEN // Lager hat Inilauf aktiv
RETURN; // Sonst kann der Inilauf nie beendet werden!
END_IF;
END_IF;
// Egal:
"DLP_Sorter".Sorter_MB3305.Separator.Default_Ziel := "Ziel_int";
"DLP_Sorter".Sorter_MB3305.Dyn.Scanner.Rec_DEST_Ziel := "Ziel_int";
// Pseudo-IDX uebergeben:
// AWL: L Rec_IDX / L DINT#0 / NE_D / BEC (Daten schon erzeugt? Ja!)
IF "DLP_Sorter".Sorter_MB3305.Dyn.Scanner.Rec_IDX <> DINT#0 THEN
RETURN;
END_IF;
"DLP_Sorter".Pseudo_IDX := "DLP_Sorter".Pseudo_IDX + DINT#1; // Da kein Leser verbaut
"DLP_Sorter".Sorter_MB3305.Dyn.Scanner.Rec_IDX := "DLP_Sorter".Pseudo_IDX; // IDX
// AWL: CLR / S M180.6 -> Set steht unter RLO=0 (CLR) und wird NICHT ausgefuehrt.
// Weiterfahrt wird ueber MSorterRein (FB5423/5) gestartet -> M180.6 bleibt unveraendert.
// AWL: BEU -> Bausteinende
ELSE
; // andere Schleusen-Nr -> nichts tun (AWL: X3305E / NOP 0)
END_CASE;
// NW3: Ende (AWL: BE)
END_FUNCTION