FUNCTION "DatenOutSort" : Void
TITLE = Datensort-Modul
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : IBAE
FAMILY : DLISTE
NAME : DatenIn
VERSION : 0.1
//COPYRIGHT by Ingenieurbüro A.Emmert
//Ortsstr.33, D-869925 Fuchstal (Germany)
//Tel.: 0049(0)8243-1254
//Version: ILS2100 / 06.11.2009
//
//Datenblock in Datenliste suchen / löschen
//SSDB:    Datenlisten-DB
//SSDW:    Datenlisten-1.DW
//SEARCHDATEN: Pointer, wo einzutragende Daten stehen (P#DB1.DBX0.0, P#M220.0) 
//AUFTRAG: XXYY
// XX:      0A = Datensatz YY lesen
//          0D = Datensätze löschen (ab DS1, Anzahl = YY) 
//          0E = Datensatz YY löschen
//
// YY: 01 - Anzahl Einträge  = Angabe welcher Datensatz / Anzahl zum Löschen  
//OUTDATEN: Pointer, wohin ausgelesene Daten übergeben werden (P#DB1.DBX0.0, 
//                                                             P#M220.0) 
//RE_VAL:  Rückmeldungen:
//   Bit0: Kein Datenlistenbereich / falscher Kopfinhalt / Endekennung
//   Bit1: SFC20-Aufruf mit Fehler
//   Bit2: Sortliste ist leer
//   Bit3: Falscher Parameter bei Aufruf
//   Bit4: Frei
//   Bit5: Undefinierte OUT-Daten
//   Bit6: Frei
//   Bit7: Frei
//
   VAR_INPUT 
      SSDB : Int;   // Datenlisten-DB
      SSDW : Int;   // Datenlisten-1.DW
      PARA : Word;   // Aufrufparameter (Auftrag , Offset/Anzahl Daten)
   END_VAR

   VAR_OUTPUT 
      OUTDATEN : Pointer;   // OutDaten-Schnittstelle
      RE_VAL : Byte;   // Rückmeldung
   END_VAR

   VAR_TEMP 
      Quelle : Any;   // Zeiger, wo Rein-Daten sind
      Ziel : Any;   // Zeiger, FIFO-Stelle
      Kopf : Byte;   // Datenliste-Kennnung (DA)
      Datensatzlaenge : Byte;   // Datensatzlänge in Word (01 - F0) F0=128
      Listenlaenge : Int;   // Länge der Datenliste (maximale Anzahl der Datensätze)
      Stammdaten : Int;   // Stammdatenlänge in Word (1 - 9)
      Belegt06 : Int;   // reserviert von Datenliste
      Belegt08 : Int;   // reserviert von Datenliste
      Belegt10 : Int;   // reserviert von Datenliste
      Belegt12 : Int;   // reserviert von Datenliste
      AnzahlEintraege : Int;   // Anzahl der eingetragenen Datensätze
      Reserve16 : Int;   // Reserve
      Reserve18 : Int;   // Reserve
      Para1 : Byte;   // 1.Aufrufparameter
      Para2 : Byte;   // 2.Aufrufparameter
      SFC_RET_VAL : Int;   // Rückmeldung SFC-Aufruf
      SFC_DB_LENGTH : Word;   // Rückmeldung SFC-Aufruf
      LeseStelle : Int;   // Stelle, wo gelesen werden soll
      EraseStelle : Int;   // Stelle, wo gelöscht werden soll
      FirstStelle : Int;   // Stelle, wo 1. zu bleibende Daten sind
      DBDatenliste : Word;   // Datenlisten-DB
      Datenlisten_Ende : Word;   // Ende der Datenliste
      AR2_Speicher : DWord;   // Adress-Register 2 zwischenspeichern
      DBOutDaten : Word;   // Out-Daten-DB, falls angegeben
      OutDaten_Pointer : DWord;   // Out-Daten-Pointer: Kennung, Adresse
      OutDaten_Startpunkt : Word;   // Out-Daten-Startpunkt: Adresse
      Datenblock_inBytes : Word;   // Datenblocklänge in Bytes
      Suchstelle : Word;   // Bei angegebenen Datensatz suchen
      SFC_WRITE_PROT : Bool;   // Rückmeldung SFC-Aufruf
      NichtCopy : Int;   // Datenmenge, die nicht vorschoben wird
      Schleife : Word;   // Loopzähler
      AR1Zeiger : DWord;   // Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)
   END_VAR


BEGIN
NETWORK
TITLE = Schnittstellen-DB sinnvoll ?
      TAR2;
      T #AR2_Speicher;//AR2 zwischenspeichern

      L #SSDB;
      T #DBDatenliste;

//      CALL  TEST_DB
//         DB_NUMBER  :=#DBDatenliste
//         RET_VAL    :=#SFC_RET_VAL
//         DB_LENGTH  :=#SFC_DB_LENGTH
//         WRITE_PROT :=#SFC_WRITE_PROT

      CALL "TEST_DB_TO_ATTR_DB"
      (  DB_Number                   := #DBDatenliste , 
         RetVal                      := #SFC_RET_VAL , 
         DB_Length                   := #SFC_DB_LENGTH , 
         Write_Prot                  := #SFC_WRITE_PROT
      );

      L #SFC_RET_VAL;
      L 2#0000_0000_0000_0000;
      <>I;
      O #SFC_WRITE_PROT;//schreibgeschützt
      SPB Err0;//kein Datenlisten-Bereich

NETWORK
TITLE = Datenlistekopf holen
//Quelle-Pointer erzeugen:
      L 16#1004;//Kennung 10 + Word=04
      T %LW0               ;//Any-Kennung, Datentyp
      L 16#000A;//10 Dw´s holen
      T %LW2               ;//Wiederholungen
      L #SSDB;
      T %LW4               ;//DB_Nummer
      L #SSDW;//Adresse
      SLD 3;
      L 16#8400_0000;//Kennung: Daten
      OD;
      T %LD6               ;//Kennung, Adresse

      CALL BLKMOV//1.-10.DW Datenliste holen
      {blk_type := 'Variant'}
      (  SRCBLK                      := #Quelle , 
         RET_VAL                     := #SFC_RET_VAL , 
         DSTBLK                      := P#L20.0 WORD 10
      );

      L #SFC_RET_VAL;
      L 2#0000_0000_0000_0000;
      <>I;
      SPB Err1;

NETWORK
TITLE = Zeigerüberprüfung
      L #Kopf;//Datenliste-Kopf
      L 16#DB;//= Datenlistekennung ?
      <>I;//Nein !
      SPB Err0;//kein Datenlistebereich

      L 1;
      L #Datensatzlaenge;//Datenblocklänge
      >I;
      SPB Err0;//kein Datenlistebereich

      L 128;
      >I;
      SPB Err0;//kein Datenlistebereich

      L 1;
      L #Listenlaenge;//Max.Anzahl von Datenblöcken
      >I;
      SPB Err0;//kein Datenlistebereich

      L 1;
      L #Stammdaten;//Anzahl der Stammdaten
      >I;
      SPB Err0;//kein Datenlistebereich

      L 9;
      >I;
      SPB Err0;//kein Datenlistebereich

      L #Stammdaten;//Anzahl der Stammdaten
      L #Datensatzlaenge;//Datenblocklänge
      >I;
      SPB Err0;//kein Datenlistebereich

      L #Listenlaenge;//Länge der Datenliste
      L #Datensatzlaenge;//Datenblocklänge
      *I;
      L 2;//DB byteorientiert
      *I;
      + 20;//Speichern ab 10.DW
      L #SSDW;
      +I;
      T #Datenlisten_Ende;
      ITD;
      SLD 3;
      T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)

      AUF DB[ #DBDatenliste];

      L #Datenlisten_Ende;
      L #SFC_DB_LENGTH;
      >I;//Datenlisten-DB ist zu kurz!
      SPB Err0;//kein Datenlisten-Bereich

      L DBW[ #AR1Zeiger];
      L 16#DBEE;//Datenliste-Endekennung ?
      <>I;//Nein !
      SPB Err0;//kein Datenlisten-Bereich

      L #Datensatzlaenge;//Datenblocklänge
      L 2;
      *I;
      T #Datenblock_inBytes;//Datenblocklänge in Bytes

NETWORK
TITLE = Auftrag kontrollieren
      L #PARA;
      T %LW40;//Aufrufparameter zwischenspeichern

      L #Para2;
      L 16#00;
      <=I;
      SPB Err3;//Falscher Aufrufparameter

      TAK;
      L #Listenlaenge;//Länge der Datenliste (maximale Anzahl der Datensätze)
      >I;
      SPB Err3;//Falscher Aufrufparameter

      L 16#0A;//XX = 0A ? (Datensatz YY lesen)
      L #Para1;
      <>I;//Nein !
      SPB W400;

//Eintrag lesen:
      L #Para2;//Datensatz YY 
      + -1;//1.Datensatz ohne Offset
      L #Datenblock_inBytes;//Datenblocklänge in bytes
      *I;
      + 20;
      L #SSDW;
      +I;
      T #LeseStelle;//Stelle, wo gelesen werden soll

      SPA Nw06;//OutDaten ok ?

W400:      L 16#0E;//XX = 0E ? (Datensatz YY löschen)
      <>I;//Nein !
      SPB W401;

//Datensatz löschen:
      L #AnzahlEintraege;
      L 0;
      ==I;
      SPB Err2;//Liste ist leer

      L #Para2;//Datensatz YY 
      L #AnzahlEintraege;//zu löschender Datensatz ist grösser als Einträge ?
      >I;//Ja !
      SPB Ende;//Keine Aktion

      L #Para2;//Datensatz YY 
      + -1;//1.Datensatz ohne Offset
      L #Datenblock_inBytes;//Datenblocklänge in bytes
      *I;
      + 20;
      L #SSDW;
      +I;
      T #EraseStelle;//Stelle, wo gelöscht werden soll

      SPA Nw08;//Daten löschen

W401:      L 16#0D;//XX = 0D ? (Datensätze YY löschen, ab 1.DS)
      L #Para1;
      <>I;//Nein !
      SPB W402;

//Datenblock löschen:
      L #AnzahlEintraege;
      L 0;
      ==I;
      SPB Err2;//Liste ist leer

      L #Para2;//Anzahl Datensätze YY 
      L #Datenblock_inBytes;//Datenblocklänge in bytes
      *I;
      + 20;
      L #SSDW;
      +I;
      T #FirstStelle;//Stelle, wo 1. zu bleibende Daten sind

      SPA Nw09;

      BEA;

W402:      SPA Err3;//Falscher Aufrufparameter

NETWORK
TITLE = Outdaten ok ?

//Out-DATEN-Pointer übernehmen:
Nw06:      L P##OUTDATEN;
      LAR2;

      L W[ AR2, P#0.0];
      T #DBOutDaten;//Outdaten-DB
      L D[ AR2, P#2.0];//Kennung, Adresse
      T #OutDaten_Pointer;

      L #DBOutDaten;//Outdaten-DB
      L 0;//Angegeben ?
      ==I;//Nein 
      SPB Nw07;

//      CALL  TEST_DB
//         DB_NUMBER  :=#DBOutDaten
//         RET_VAL    :=#SFC_RET_VAL
//         DB_LENGTH  :=#SFC_DB_LENGTH
//         WRITE_PROT :=#SFC_WRITE_PROT

      CALL "TEST_DB_TO_ATTR_DB"
      (  DB_Number                   := #DBOutDaten , 
         RetVal                      := #SFC_RET_VAL , 
         DB_Length                   := #SFC_DB_LENGTH , 
         Write_Prot                  := #SFC_WRITE_PROT
      );


      L #SFC_RET_VAL;
      L 2#0000_0000_0000_0000;//Fehler vorhanden ?
      <>I;//Ja !
      SPB Err5;//Undefinierte Outdaten

      L D[ AR2, P#2.0];//Kennung, Adresse
      L 16#00FF_FFFF;//Ohne Kennung
      UW;
      SRW 3;//Ohne Bit
      T #OutDaten_Startpunkt;

      L #OutDaten_Startpunkt;
      L #SFC_DB_LENGTH;
      >I;//Outdaten-DB ist zu kurz
      SPB Err5;//Undefinierte Outdaten

NETWORK
TITLE = Daten aus Datenliste lesen (in OUTDaten übergeben)

//Quelle-Pointer erzeugen:
Nw07:      L 16#1004;//Kennung 10 + Word=04
      T %LW0;
      T %LW10;//Any-Kennung, Datentyp
      L #Datensatzlaenge;//Datenwords speichern
      T %LW2;
      T %LW12;//Wiederholungen

//DATEN-Pointer übernehmen:
      L #SSDB;
      T %LW4;//DB_Nummer
      L #LeseStelle;//Adresse
      SLD 3;
      L 16#8400_0000;//Kennung: Daten
      OD;
      T %LD6;//Kennung, Adresse

//Ziel-Pointer erzeugen:
//Kennung + Datenbytes s.o.

      L #DBOutDaten;
      T %LW14;//DB_Nummer
      L #OutDaten_Pointer;
      T %LD16;//Kennung, Adresse

      CALL BLKMOV//DatenSortliste-Daten speichern
      {blk_type := 'Variant'}
      (  SRCBLK                      := #Quelle , 
         RET_VAL                     := #SFC_RET_VAL , 
         DSTBLK                      := #Ziel
      );

      L #SFC_RET_VAL;
      L 2#0000_0000_0000_0000;
      <>I;
      SPB Err1;

      SPA Ende;

NETWORK
TITLE = Daten aus Datenliste löschen ?

//Gemeinsame Daten für Pointer erzeugen:
Nw08:      L 16#1004;//Kennung 10 + Word=04
      T %LW0;
      T %LW10;//Any-Kennung, Datentyp

      L #Datensatzlaenge;//Datensatzlänge
      L #Para2;//Datensatz YY 
      *I;
      T #NichtCopy;//Datenmenge, die nicht vorschoben wird

      L #Listenlaenge;//Länge der Datenliste
      L #Datensatzlaenge;//Datenblocklänge
      *I;//Gesamtdatenlänge in Words
      L #NichtCopy;//Datenmenge, die nicht vorschoben wird
      -I;//abziehen
      T %LW2;
      T %LW12;//Wiederholungen

      L #SSDB;
      T %LW4;
      T %LW14;//DB_Nummer

//Quelle-Pointer erzeugen:
      L #EraseStelle;//Stelle, wo gelöscht werden soll
      L #Datenblock_inBytes;//Datenblocklänge in Bytes
      +I;
      SLD 3;
      L 16#8400_0000;//Kennung: Daten
      OD;
      T %LD6;//Kennung, Adresse

//Ziel-Pointer erzeugen:
      L #EraseStelle;//Stelle, wo gelöscht werden soll
      SLD 3;
      L 16#8400_0000;//Kennung: Daten
      OD;
      T %LD16;//Kennung, Adresse

//Daten verschieben:
      CALL BLKMOV//DatenSortliste-Daten verschieben
      {blk_type := 'Variant'}
      (  SRCBLK                      := #Quelle , 
         RET_VAL                     := #SFC_RET_VAL , 
         DSTBLK                      := #Ziel
      );

      L #SFC_RET_VAL;
      L 2#0000_0000_0000_0000;
      <>I;
      SPB Err1;

//Letzte Daten löschen:
      L #Datenlisten_Ende;//Ende des Datenbereichs
      L #Datenblock_inBytes;//Datenblocklänge in Bytes
      -I;//Ab hier löschen !
      ITD;
      SLD 3;
      T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)

      L #Datensatzlaenge;//Datensatzlänge
L080:      T #Schleife;

      AUF DB[ #DBDatenliste];

      L 0;//Daten löschen
      T DBW[ #AR1Zeiger];

      L #AR1Zeiger;
      SRD 3;
      L 2;
      +D;
      SLD 3;
      T #AR1Zeiger;

      L #Schleife;
      LOOP L080;

      L #AnzahlEintraege;//Anzahl der eingetragenen Datensätze
      + -1;
      T #AnzahlEintraege;

      L 0;
      >=I;
      SPB w080;

      T #AnzahlEintraege;//Minimum übergeben

w080:      L #SSDW;
      + 14;//Anzahl der Einträge
      ITD;
      SLD 3;
      T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)

      AUF DB[ #DBDatenliste];
      L #AnzahlEintraege;//Anzahl der eingetragenen Datensätze
      T DBW[ #AR1Zeiger];//Anzahl der Einträge

      SPA Ende;

NETWORK
TITLE = Datensätze aus Datenliste löschen ?

//Gemeinsame Daten für Pointer erzeugen:
Nw09:      L 16#1004;//Kennung 10 + Word=04
      T %LW0;
      T %LW10;//Any-Kennung, Datentyp

      L #Datensatzlaenge;//Datensatzlänge
      L #Para2;//Anzahl Datensätze YY 
      *I;
      T #NichtCopy;//Datenmenge, die nicht vorschoben wird

      L #Listenlaenge;//Länge der Datenliste
      L #Datensatzlaenge;//Datenblocklänge
      *I;//Gesamtdatenlänge in Words
      L #NichtCopy;//Datenmenge, die nicht vorschoben wird
      -I;//abziehen
      T %LW2;
      T %LW12;//Wiederholungen

      L #SSDB;
      T %LW4;
      T %LW14;//DB_Nummer

//Quelle-Pointer erzeugen:
      L #FirstStelle;//Stelle, wo 1. zu bleibende Daten sind
      SLD 3;
      L 16#8400_0000;//Kennung: Daten
      OD;
      T %LD6;//Kennung, Adresse

//Ziel-Pointer erzeugen:
      L #SSDW;
      + 20;//1.DS
      SLD 3;
      L 16#8400_0000;//Kennung: Daten
      OD;
      T %LD16;//Kennung, Adresse

//Daten verschieben:
      CALL BLKMOV//DatenSortliste-Daten verschieben
      {blk_type := 'Variant'}
      (  SRCBLK                      := #Quelle , 
         RET_VAL                     := #SFC_RET_VAL , 
         DSTBLK                      := #Ziel
      );

      L #SFC_RET_VAL;
      L 2#0000_0000_0000_0000;
      <>I;
      SPB Err1;

//Letzte Daten löschen:
      L #Datenlisten_Ende;//Ende des Datenbereichs
      L #NichtCopy;//Datenmenge, die nicht vorschoben wird
      -I;
      L #NichtCopy;//2 mal, da Angabe in Word (Angabe in Byte benötigt!)
      -I;//Ab hier löschen !
      ITD;
      SLD 3;
      T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)

      L #NichtCopy;//Datenmenge, die nicht vorschoben wird
L090:      T #Schleife;

      AUF DB[ #DBDatenliste];

      L 0;//Daten löschen
      T DBW[ #AR1Zeiger];

      L #AR1Zeiger;
      SRD 3;
      L 2;
      +D;
      SLD 3;
      T #AR1Zeiger;

      L #Schleife;
      LOOP L090;

      L #AnzahlEintraege;//Anzahl der eingetragenen Datensätze
      L #Para2;//Anzahl Datensätze YY 
      -I;
      T #AnzahlEintraege;

      L 0;
      >=I;
      SPB w090;

      T #AnzahlEintraege;//Minimum übergeben

w090:      L #SSDW;
      + 14;//Anzahl der Einträge
      ITD;
      SLD 3;
      T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)

      AUF DB[ #DBDatenliste];
      L #AnzahlEintraege;//Anzahl der eingetragenen Datensätze
      T DBW[ #AR1Zeiger];//Anzahl der Einträge

      SPA Ende;

NETWORK
TITLE = Fehlerausgabe / RET_VAL
Ende:      SET;//VKE = 1 ohne Fehler !!!
      L 2#0000_0000_0000_0000;//Ok-Status
      SPA Ok;
Err0:      L 2#0000_0000_0000_0001;//Kein Datenlistebereich
      SPA Err;
Err1:      L 2#0000_0000_0000_0010;//SFC20-Aufruf mit Fehler
      SPA Err;
Err2:      L 2#0000_0000_0000_0100;//Sortliste ist leer
      SPA Err;
Err3:      L 2#0000_0000_0000_1000;//Falscher Parameter bei Aufruf
      SPA Err;
Err5:      L 2#0000_0000_0010_0000;//Undefinierte OUTDaten

Err:      CLR;//VKE = 0 bei Fehler !!!

Ok:      T #RE_VAL;
      SAVE;//VKE in BIE-Bit speichern  

      L #AR2_Speicher;//AR2 zurückspeichern
      LAR2;

END_FUNCTION

