FUNCTION "DatenFindOffsetSort" : 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
//
//Offsetdaten in sortierter Datenliste suchen
//SSDB:    Datenlisten-DB
//SSDW:    Datenlisten-1.DW
//SEARCHDATEN: Pointer, wo einzutragende Daten stehen (P#DB1.DBX0.0, P#M220.0) 
//AUFTRAG: XXYY
// XX:      00 = angegebenen Datensatz suchen
//     02 - 80 = Stammdaten beginnen ab angegebenen Datenwort 
//          F1 = 1.Datensatz lesen
//          FF = nächsten vorhandenen Eintrag lesen (ab letzten Zugriff)
// YY: 01 - 09  = Anzahl der Stammdaten (falls abweichend vom Datenlistenkopf!)  
//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: Listenende ist erreicht
//   Bit3: Falscher Parameter bei Aufruf
//   Bit4: Undefinierte Stammdaten
//   Bit5: Undefinierte OUT-Daten
//   Bit6: Datensatz ist nicht vorhanden
//   Bit7: Datensatz ist vorhanden
//
   VAR_INPUT 
      SSDB : Int;   // Datenlisten-DB
      SSDW : Int;   // Datenlisten-1.DW
      PARA : Word;   // Aufrufparameter (Auftrag / Anzahl Zusatzdaten)
      SEARCHDATEN : Pointer;   // Such-Daten-Schnittstelle
   END_VAR

   VAR_OUTPUT 
      RE_VAL : Byte;   // Rückmeldung
      OUTDATEN : Pointer;   // OutDaten-Schnittstelle
      Position : Int;   // Daten stehen an angegebener Position in Datenbank
   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
      Suchzeiger : Int;   // Suchzeiger
      DBDatenliste : Word;   // Datenlisten-DB
      OffsetDaten_1 : Int;   // Stammdaten beginnen ab hier
      SFC_RET_VAL : Int;   // Rückmeldung SFC-Aufruf
      SFC_DB_LENGTH : Word;   // Rückmeldung SFC-Aufruf
      Datenlisten_Ende : Word;   // Ende der Datenliste
      AR2_Speicher : DWord;   // Adress-Register 2 zwischenspeichern
      Schleife : Word;   // Loopzähler
      DBSuchDaten : Word;   // Such-Daten-DB, falls angegeben
      SuchDaten_Pointer : DWord;   // Such-Daten-Pointer: Kennung, Adresse
      SuchDaten_Startpunkt : Word;   // Such-Daten-Startpunkt: Adresse
      DBOutDaten : Word;   // Out-Daten-DB, falls angegeben
      OutDaten_Pointer : DWord;   // Out-Daten-Pointer: Kennung, Adresse
      OutDaten_Startpunkt : Word;   // Out-Daten-Startpunkt: Adresse
      IndPointer : DWord;   // Zeiger für IndDB
      Daten_1 : Word;   // 1.Datenwort der Indaten
      Datenblock_inBytes : Word;   // Datenblocklänge in Bytes
      Suchstelle : Word;   // Bei angegebenen Datensatz suchen
      SFC_WRITE_PROT : Bool;   // Rückmeldung SFC-Aufruf
      Weitersuchen : Bool;   // Weitersuchen ist aktiv
      Offsetsuchen : Bool;   // Offsetsuchen ist aktiv
      AR1Zeiger : DWord;   // Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)
      tRE_VAL : Byte;   // Rückmeldung
   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;//= Sort-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#DAEE;//Datenliste-Endekennung ?
      <>I;//Nein !
      U(;
      TAK;
      L 16#DBEE;//Sort-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
      SET;
      R #Weitersuchen;//Weitersuchen ist aktiv
      R #Offsetsuchen;//Offsetsuchen ist aktiv
      L 0;//Vorerst kein Offset
      T #OffsetDaten_1;

      L #PARA;
      T %LW40        ;//Aufrufparameter zwischenspeichern

      L 16#00;//XX = 00 ?
      L #Para1;
      ==I;//Ja!
      SPB W401;

      L 16#E1;//XX = E1 ?
      ==I;//Ja!
      SPB Err3;//Falscher Aufrufparameter

      L 16#F1;//XX = F1 ?
      L #Para1;
      <>I;//Nein !
      SPB W400;

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

      SET;
      S #Weitersuchen;

      L #SSDW;
      + 20;
      T #Suchzeiger;

      SPA Nw08;//OutDaten ok ?

W400:      L 16#FF;//XX = FF ?
      <>I;//Nein !
      SPB W403;

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

      SET;
      S #Weitersuchen;

      L #Suchzeiger;//Alter Suchzeiger
      L #Datenblock_inBytes;//Datenblocklänge in bytes
      +I;//Nächsten Datensatz suchen
      T #Suchzeiger;//Neuer Suchzeiger

      L #Datenblock_inBytes;//Datenblocklänge in bytes
      L #Listenlaenge;//Alle möglichen Einträge
      *I;//Gesamtlänge
      L #SSDW;//Startpunkt
      +I;
      + 20;//Offset 1.Daten
      L #Suchzeiger;//Schreibzeiger
      >I;//Noch nicht am Ende !
      SPB Nw08;//OutDaten ok ?

      SPA Err2;//Listenende erreicht

W403:      L 16#02;//XX < 02 ?
      L #Para1;
      >I;//Ja!
      SPB Err3;//Falscher Aufrufparameter

      L 16#80;//XX > 80 ?
      >I;//Ja!
      SPB Err3;//Falscher Aufrufparameter

      TAK;
      L #Datensatzlaenge;//XX > Datensatzlänge
      >I;//Ja!
      SPB Err3;//Falscher Aufrufparameter

      TAK;
      + -1;//Angegebener Offset -1
      L 2;//DB byteorientiert
      *I;
      T #OffsetDaten_1;//Richtiger Offset der 1.Stammdaten

      L 0;
      T #Suchzeiger;//Suche ab Anfang

      SET;
      S #Offsetsuchen;

W401:      L 16#00;//=0 ?
      L #Para2;//2.Aufrufparameter
      ==I;//Ja !
      SPB W402;

      T #Stammdaten;//Anzahl der Stammdaten
      L #Datensatzlaenge;//Datenblocklänge
      >I;
      SPB Err3;//Falscher Aufrufparameter

      L 1;
      L #Stammdaten;//Anzahl der Stammdaten
      >I;
      SPB Err3;//Falscher Aufrufparameter

      L 9;
      >I;
      SPB Err3;//Falscher Aufrufparameter

W402:      UN #Offsetsuchen;
      SPB Nw05;

      L #Para1;//Offset
      + -1;
      L #Stammdaten;
      +I;//Letzte Stammdaten zu groß ?
      L #Datensatzlaenge;
      >I;//Ja!
      SPB Err3;//Falscher Aufrufparameter

NETWORK
TITLE = Suchdaten definiert ?
//Such-DATEN-Pointer übernehmen:
Nw05:      L #AnzahlEintraege;//Anzahl der eingetragenen Datensätze
      L 0;//Eintrag vorhanden ?
      ==I;//Nein !
      SPB Err6;//Datensatz ist nicht vorhanden

      L 0;
      T #Suchzeiger;//Suchzeiger

      L P##SEARCHDATEN;
      LAR2;

      L W[ AR2, P#0.0];
      T #DBSuchDaten;//Suchdaten-DB
      L D[ AR2, P#2.0];//Kennung, Adresse
      T #SuchDaten_Pointer;

      L #DBSuchDaten;//Suchdaten-DB
      L 0;//Angegeben ?
      ==I;//Nein 
      SPB W501;

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

      CALL "TEST_DB_TO_ATTR_DB"
      (  DB_Number                   := #DBSuchDaten , 
         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 Err4;//Undefinierte Stammdaten

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

      L #Datensatzlaenge;//Datenblocklänge
      L 2;//DB byteorientiert
      *I;
      L #SuchDaten_Startpunkt;
      +I;
      L #SFC_DB_LENGTH;
      >I;//Suchdaten-DB ist zu kurz
      SPB Err4;//Undefinierte Stammdaten

W501:      L #SuchDaten_Pointer;
      LAR2;

      L #DBSuchDaten;//Suchdaten-DB
      L 0;//Angegeben ?
      ==I;//Nein 
      SPB W502;

      AUF DB[ #DBSuchDaten];

W502:      L W[ AR2, P#0.0];//Suchdaten überprüfen
      T #Daten_1;//1.Suchdaten speichern

      L #Stammdaten;
L500:      T #Schleife;

      L #DBSuchDaten;//Suchdaten-DB
      L 0;//Angegeben ?
      ==I;//Nein 
      SPB W503;

      AUF DB[ #DBSuchDaten];

W503:      L W[ AR2, P#0.0];//Suchdaten überprüfen
      L 0;//Etwas angegeben ?
      <>I;//Ja !
      SPB Nw07;//Weiter

      +AR2 P#2.0;

      L #Schleife;
      LOOP L500;

      SPA Err4;//Undefinierte Stammdaten

NETWORK
TITLE = Kontrolle auf gleiche Stammdaten
Nw07:      L #Suchzeiger;//Suchzeiger
      L 0;//Angegeben ?
      ==I;//Nein !
      SPB W700;//Suche bei 1.Datensatz beginnen

      L #Suchzeiger;//Suchzeiger
      + -20;//Zeiger 1.Daten
      L #Datenblock_inBytes;//Datenblocklänge in Bytes
      /I;//Ermittlung der wievielten Daten -1
      SRD 16;//Rest ermitteln
      L 0;//= 0 ?
      <>I;//Suchzeiger nicht im Raster !
      SPB W700;//Suche bei 1.Datensatz beginnen

      L 0;//Bei angegebener Stelle suchen
      T #Suchstelle;//Such bei X-ten Datensatz

      SPA W701;

W700:      L 1;//Suche bei 1.Datensatz beginnen
      T #Suchstelle;//Such bei X-ten Datensatz
      L #SSDW;
      + 20;//Offset für 1.Daten
      T #Suchzeiger;//Suchzeiger

W701:      L #Suchzeiger;//Suchzeiger
      L #OffsetDaten_1;//Richtiger Offset der 1.Stammdaten
      +I;
      ITD;
      SLD 3;
      T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)

      L #SuchDaten_Pointer;
      LAR2;

      L #Stammdaten;//Anzahl der Stammdaten
L700:      T #Schleife;

      L #DBSuchDaten;//Suchdaten-DB
      L 0;//Angegeben ?
      ==I;//Nein 
      SPB W702;

      AUF DB[ #DBSuchDaten];

W702:      L W[ AR2, P#0.0];//Suchdaten überprüfen mit
      AUF DB[ #DBDatenliste];
      L DBW[ #AR1Zeiger];//Datenliste-Daten lesen
      <>I;//nicht identisch !
      SPB W703;

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

      +AR2 P#2.0;

      L #Schleife;
      LOOP L700;

      L 2#0000_0000_1000_0000;//Daten sind vorhanden
      T #tRE_VAL;//Ok-Status

      SPA Nw08;//Datensatz ist in Liste enthalten

W703:      L 0;//Suche bei 1.Datensatz  begonnen
      L #Suchstelle;//Such bei X-ten Datensatz
      ==I;//Nein !
      SPB W700;

      L #Suchstelle;//Such bei X-ten Datensatz
      + 1;
      T #Suchstelle;//Such bei X-ten Datensatz
      L #AnzahlEintraege;//Anzahl der eingetragenen Datensätze
      <=I;//Alle Datensätze sind durchsucht
      SPB W705;//Nein !

      SPA Err6;//Datensatz ist nicht vorhanden

W705:      L #Datenblock_inBytes;//Datenblocklänge in bytes
      L #Suchzeiger;//Suchzeiger
      +I;
      T #Suchzeiger;//Suchzeiger
      SPA W701;

NETWORK
TITLE = Outdaten ok ?
//Out-DATEN-Pointer übernehmen:
Nw08:      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 Nw09;

//      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:
Nw09:      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 #Suchzeiger;//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//Datenliste-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;

      L #SSDW;
      + 12;//im 12.DW speichern
      ITD;
      SLD 3;
      T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)

      L #Suchzeiger;//Suchzeiger
      AUF DB[ #DBDatenliste];
      T DBW[ #AR1Zeiger];//Speicherung letzter Zugriff

      L #Suchzeiger;//Suchzeiger
      + -20;//Offeset 1.DS
      L #Datenblock_inBytes;//Datenblocklänge in Bytes
      /I;
      + 1;//Position errechnen
      T #Position;//Daten stehen an angegebener Position in Datenbank

NETWORK
TITLE = Weitersuchen aktiv ? Datensatz vorhanden oder 0 ?
      UN #Weitersuchen;
      SPB Ende;

      L #OutDaten_Pointer;
      LAR2;

      L #Datensatzlaenge;
L110:      T #Schleife;

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

      AUF DB[ #DBOutDaten];

W111:      L W[ AR2, P#0.0];//Outdaten überprüfen
      L 0;//Etwas angegeben ?
      <>I;//Ja !
      SPB W112;//Ok

      +AR2 P#2.0;

      L #Schleife;
      LOOP L110;

      L 2#0000_0000_0100_0000;//Daten sind nicht vorhanden
      T #tRE_VAL;//Ok-Status
      SPA Ende;

W112:      L 2#0000_0000_1000_0000;//Daten sind vorhanden
      T #tRE_VAL;//Ok-Status
      SPA Ende;

NETWORK
TITLE = Fehlerausgabe / RET_VAL
Ende:      SET;//VKE = 1 ohne Fehler !!!
      L #tRE_VAL;//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;//Listenende ist erreicht
      SPA Err;
Err3:      L 2#0000_0000_0000_1000;//Falscher Parameter bei Aufruf
      SPA Err;
Err4:      L 2#0000_0000_0001_0000;//Undefinierte Suchdaten
      SPA Err;
Err5:      L 2#0000_0000_0010_0000;//Undefinierte OUTDaten
      SPA Err;
Err6:      L 2#0000_0000_0100_0000;//Datensatz nicht vorhanden

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

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

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

NETWORK
TITLE = 
      L #tRE_VAL;
      T #RE_VAL;


END_FUNCTION

