FUNCTION "DatenIn" : Void
TITLE = Datenlisten-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: P&O / 10.2024
//Version: ILS2100 / 06.11.2009
//
//Datenblock in Datenliste eintragen
//SSDB:    Datenlisten-DB
//SSDW:    Datenlisten-1.DW
//INDATEN: Pointer, wo einzutragende Daten stehen (P#DB1.DBX0.0, P#M220.0) 
//RE_VAL:  Rückmeldungen:
//   Bit0: Kein Datenlistenbereich / falscher Kopfinhalt / Endekennung
//   Bit1: SFC20-Aufruf mit Fehler
//   Bit2: Liste ist voll
//   Bit3: Frei
//   Bit4: Undefinierte Indaten
//   Bit5: Frei
//   Bit6: Daten wurden überschrieben
//   Bit7: Eintrag ist richtig erfolgt
//
   VAR_INPUT 
      SSDB : Int;   // Datenlisten-DB
      SSDW : Int;   // Datenlisten-1.DW
      INDATEN : Pointer;   // InDaten-Schnittstelle
   END_VAR

   VAR_OUTPUT 
      RE_VAL : Byte;
   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)
      IndDB : Word;   // Indizierter DB (nur bei Stammdaten = 1 erlaubt !!!)
      IndDB_Laenge : Int;   // Länge des indizierten DB in Einträge (nur bei Stammdaten = 1 erlaubt !!!)
      IndDaten_FC : Int;   // FC zum Wandeln der indizierte Daten (nur bei Stammdaten = 1 erlaubt !!!)
      Schreibzeiger : Int;   // Speicherung des letzten Zugriffs / Schreibzeiger
      Belegt14 : Int;   // reserviert von Sort-Datenliste
      AnzahlEintraege : Int;   // Anzahl der eingetragenen Datensätze (nicht bei ind.Zugriff!)
      Reserve18 : Int;   // Reserve
      DBDatenliste : Word;   // Datenlisten-DB
      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
      DBInDaten : Word;   // Indaten-DB, falls angegeben
      InDaten_Pointer : DWord;   // In-Daten-Pointer: Kennung, Adresse
      InDaten_Startpunkt : Word;   // In-Daten-Startpunkt: Adresse
      IndPointer : DWord;   // Zeiger für IndDB
      Daten_1 : Word;   // 1.Datenwort der Indaten
      Daten_2 : DWord;   // 1+2.Datenwort der Indaten (falls ind.Suchen mit Stammdaten 2)
      LeerZeiger : Word;   // Zeiger für Leerzelle
      Datenblock_inBytes : Word;   // Datenblocklänge in Bytes
      Suchstelle : Word;   // Bei angegebenen Datensatz suchen
      SFC_WRITE_PROT : Bool;   // Rückmeldung SFC-Aufruf
      Indok : Bool;   // Indizierung möglich
      IndZeiger_ok : Bool;   // Indizier-Zeiger angegeben
      Sortliste : Bool;   // Sortliste wird durchsucht
      tRE_VAL : Byte;   // Rückmeldung
      AR1Zeiger : DWord;   // Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)
      DB_Länge : Int;
      Wandel_FC : Word;   // Wandel-FC
   END_VAR


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

      L #SSDB;
      T #DBDatenliste;

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

      CALL "BCD (4stellig)_to_INT"
      (  BCD_Wert                    := #SFC_DB_LENGTH , 
         Int_Wert                    := #DB_Länge
      );

      L #SFC_RET_VAL;
      L 2#0000_0000_0000_0000;
      <>I;
      O #SFC_WRITE_PROT;
      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;//Ja !
      = #Sortliste;//Sortliste wird durchsucht
      SPB w030;

      TAK;
      L 16#DA;//= Datenlistekennung ?
      <>I;//Nein !
      SPB Err0;//kein Datenlistebereich

w030:      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 #DB_Länge;
      >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 = Indaten definiert ?
//In-DATEN-Pointer übernehmen:
      L P##INDATEN;
      LAR2;

      L W[ AR2, P#0.0];
      T #DBInDaten;//Indaten-DB

      L #DBInDaten;//Indaten-DB
      L 0;//Angegeben ?
      ==I;//Nein 
      SPB W401;

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

      CALL "BCD (4stellig)_to_INT"
      (  BCD_Wert                    := #SFC_DB_LENGTH , 
         Int_Wert                    := #DB_Länge
      );

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

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

      L #Datensatzlaenge;//Datenblocklänge
      L 2;//DB byteorientiert
      *I;
      L #InDaten_Startpunkt;
      +I;
      L #DB_Länge;
      >I;//Indaten-DB ist zu kurz
      SPB Err4;//Undefinierte Indaten

W401:      L D[ AR2, P#2.0];//Kennung, Adresse
      T #InDaten_Pointer;
      LAR2;

      L #DBInDaten;//Indaten-DB
      L 0;//Angegeben ?
      ==I;//Nein 
      SPB W402;

      AUF DB[ #DBInDaten];

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

      L #Stammdaten;
L400:      T #Schleife;

      L #DBInDaten;//Indaten-DB
      L 0;//Angegeben ?
      ==I;//Nein 
      SPB W403;

      AUF DB[ #DBInDaten];

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

      +AR2 P#2.0;

      L #Schleife;
      LOOP L400;

      SPA Err4;//Undefinierte Indaten

NETWORK
TITLE = Indiziert speichern ?
Nw05:      SET;
      R #Indok;//Indizierung möglich
      R #IndZeiger_ok;//Indizier-Zeiger angegeben

      L #IndDB;//Indizierter DB
      L 0;//Angegeben ?
      ==I;//Nein !
      O #Sortliste;//Sortliste wird durchsucht
      SPB Nw06;

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

      CALL "BCD (4stellig)_to_INT"
      (  BCD_Wert                    := #SFC_DB_LENGTH , 
         Int_Wert                    := #DB_Länge
      );

      L #SFC_RET_VAL;
      L 2#0000_0000_0000_0000;
      <>I;
      O #SFC_WRITE_PROT;
      SPB Nw06;//kein Indizier-DB vorhanden


      L #IndDB_Laenge;//Länge des Indizierten DB überschritten ?
      L 2;//DB byteorientiert
      *I;
      L #DB_Länge;
      >I                       ;//Indizier-DB ist zu kurz
      SPB Nw06;//Zeiger ausserhalb Ind.DB

      L #Stammdaten;//Stammdaten
      L 3                  ;//zu viele Stammdaten ?
      >=I                      ;//Ja !
      SPB Nw06               ;//ohne Indizierung weiter

      L #IndDaten_FC;//Offset zum Abziehen
      T #Wandel_FC;
      L 0;//Parameter vorhanden ?
      <=I;//Nein
      SPB NoFC;//Bei diesem Schritt weiter 

      L #Daten_1           ;//Stammdaten (1.DW)
      T "MW90";//übergeben
      L #Daten_2           ;//Stammdaten (2.DW)
      T "MD94"             ;//übergeben

      UC FC[ #Wandel_FC];//Beeinflussung der Weiterfahrt

      L "MW92";//Rückwert von FC

      SPA Ret;

NoFC:      L #Daten_1;//Stammdaten
Ret:      T #IndPointer;//Stelle, wo Zeiger hinterlegt ist
      L 0;
      <I;//negativ
      SPB Nw06;//Zeiger = 0

      L #IndDB_Laenge;//Länge des Indizierten DB überschritten ?
      L #IndPointer;//Stelle, wo Zeiger hinterlegt ist
      <=I;//Ja !
      SPB Nw06;//Zeiger ausserhalb Ind.DB

      L 2;
      *I;//DB byteorientiert
      SLD 3;//Pointer erzeugen
      T #IndPointer;//Pointer, wo Zeiger hinterlegt ist

      AUF DB[ #IndDB];//Indizierter DB
      L DBW[ #IndPointer];
      T #Schreibzeiger;//Schreibzeiger

      AUF DB[ #DBDatenliste];//Datenliste DB

      SET;
      S #Indok;//Indizierung möglich
      S #IndZeiger_ok;//Indizier-Zeiger angegeben

NETWORK
TITLE = Kontrolle auf gleiche Stammdaten
Nw06:      L 0;//nicht gespeichert
      T #LeerZeiger;//Zeiger Leerzelle

      L #Schreibzeiger;//Schreibzeiger
      L 0;//Angegeben ?
      ==I;//Nein !
      SPB W600;//Suche bei 1.Datensatz beginnen

      L #Schreibzeiger;//Schreibzeiger
      + -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;//Schreibzeiger nicht im Raster !
      SPB W600;//Suche bei 1.Datensatz beginnen

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

      SPA W601;

W600:      L 1;//Suche bei 1.Datensatz beginnen
      T #Suchstelle;//Such bei X-ten Datensatz
      SET;
      R #IndZeiger_ok;//Indizier-Zeiger angegeben
      L #SSDW;
      + 20;//Offset für 1.Daten
      T #Schreibzeiger;//Schreibzeiger

W601:      L #Schreibzeiger;//Schreibzeiger
      ITD;
      SLD 3;
      T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)

      L #InDaten_Pointer;
      LAR2;

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

      L #DBInDaten;//Indaten-DB
      L 0;//Angegeben ?
      ==I;//Nein 
      SPB W602;

      AUF DB[ #DBInDaten];

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

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

      +AR2 P#2.0;

      L #Schleife;
      LOOP L600;

      L 2#0000_0000_1100_0000;//Daten werden gespeichert + überschrieben
      T #tRE_VAL;//Ok-Status

      SPA Nw07;//Datensatz ist in Liste enthalten

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

      L #LeerZeiger;//Zeiger Leerzelle
      L 0;//Gespeichert ?
      <>I;//Ja !
      SPB W604;

      L #Schreibzeiger;//Schreibzeiger
      ITD;
      SLD 3;
      T #AR1Zeiger;///Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)

      L #Datensatzlaenge;
L601:      T #Schleife;
      L DBW[ #AR1Zeiger]   ;//Daten lesen
      L 0;//Leerzelle ?
      <>I;//Nein !
      SPB W604;

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

      L #Schleife;
      LOOP L601;

      L #Schreibzeiger;//Schreibzeiger
      T #LeerZeiger;//Zeiger Leerzelle

W604:      L #Suchstelle;//Such bei X-ten Datensatz
      + 1;
      T #Suchstelle;//Such bei X-ten Datensatz
      L #Listenlaenge;//Anzahl aller Daten in Datenliste
      <=I;//Alle Datensätze sind durchsucht
      SPB W605;//Nein !

      L 0;//Gefunden ?
      L #LeerZeiger;//Zeiger Leerzelle
      ==I;//Nein !
      SPB Err2;//Datenliste ist voll

      T #Schreibzeiger;//Schreibzeiger
      L 2#0000_0000_1000_0000;//Daten werden gespeichert    
      T #tRE_VAL;//Ok-Status

      SPA Nw07;

W605:      L #Datenblock_inBytes;//Datenblocklänge in bytes
      L #Schreibzeiger;//Schreibzeiger
      +I;
      T #Schreibzeiger;//Schreibzeiger
      SPA W601;

NETWORK
TITLE = Daten in Datenliste schreiben
//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 #DBInDaten;
      T %LW4;//DB_Nummer
      L #InDaten_Pointer;
      T %LD6;//Kennung, Adresse

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

      L #SSDB;
      T %LW14;//DB_Nummer
      L #Schreibzeiger;//Adresse
      SLD 3;
      L 16#8400_0000;//Kennung: Daten
      OD;
      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;

      U #Sortliste;//Sortliste wird durchsucht
      SPB Nw8;

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

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

      L #tRE_VAL           ;//Ok-Status
      L 2#0000_0000_1100_0000;//Daten werden gespeichert + überschrieben ?
      ==I;//Ja !
      O #Indok             ;//Indizierung möglich ((Dann nicht!)
      SPB Nw8                ;//Kein Neueintrag !

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

      AUF DB[ #DBDatenliste];
      L DBW[ #AR1Zeiger];//Anzahl der Einträge
      + 1;//Einträge +1
      T DBW[ #AR1Zeiger];//Anzahl der Einträge

NETWORK
TITLE = Indizierung ok ?
Nw8:      UN #Indok;//Indizierung möglich
      O #IndZeiger_ok;//Indizier-Zeiger angegeben
      SPB Ende;

      AUF DB[ #IndDB];//Indizierter DB

      L #Schreibzeiger;//Schreibzeiger
      T DBW[ #IndPointer];

      AUF DB[ #DBDatenliste];//Datenliste DB

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;//Datenliste ist voll
      SPA Err;
Err4:      L 2#0000_0000_0001_0000;//Undefinierte Indaten

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 = Ausgangsvariablen schreiben
      L #tRE_VAL;
      T #RE_VAL;


END_FUNCTION

