=== FC 88: DatenInSort  [STL] ===
INTERFACE:
  Input:
    SSDB : Int                                          // Datenlisten-DB
    SSDW : Int                                          // Datenlisten-1.DW
    INDATEN : Pointer                                   // InDaten-Schnittstelle
  Output:
    RE_VAL : Byte                                       // Rückmeldung
  InOut:
  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
    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
    Sort_Daten : DInt                                   // Einzusortierende Daten (DWord)
    Datenblock_inBytes : Word                           // Datenblocklänge in Bytes
    SFC_WRITE_PROT : Bool                               // Rückmeldung SFC-Aufruf
    Lesestelle : Int                                    // An dieser Stelle Datensatz lesen
    Min_Lesestelle : Int                                // Minimal sinnvolle Lesestelle
    Max_Lesestelle : Int                                // Maximal sinnvolle Lesestelle
    Savestelle : Int                                    // An dieser Stelle wird In-Datensatz gespeichert
    Lese_Daten : DInt                                   // In Tabelle gelesenen Daten
    Holstelle : Int                                     // Freiraum schaffen: Stelle zum Daten holen
    Bringstelle : Int                                   // Freiraum schaffen: Stelle zum Daten schreiben
    Holzeiger : DWord                                   // Freiraum schaffen: Zeiger zum Daten holen
    Bringzeiger : DWord                                 // Freiraum schaffen: Zeiger zum Daten schreiben
    AR1Zeiger : DWord                                   // Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)
  Constant:
  Return:
    Ret_Val : Void

--- NW 1: 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 FC "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
      JC     Err0                                            // kein Datenlisten-Bereich


--- NW 2: 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 SYS "BLKMOV" (SRCBLK:=Quelle, RET_VAL:=SFC_RET_VAL, DSTBLK:=P#L20.0 WORD 10)   // 1.-10.DW Datenliste holen

      L      SFC_RET_VAL
      L      2#0000_0000_0000_0000
      <>I
      JC     Err1


--- NW 3: Zeigerüberprüfung ---
      L      Kopf                                            // Datenliste-Kopf
      L      16#DB                                           // = Datenlistekennung ?
      <>I                                                    // Nein !
      JC     Err0                                            // kein Datenlistebereich

      L      1
      L      Datensatzlaenge                                 // Datenblocklänge
      >I
      JC     Err0                                            // kein Datenlistebereich

      L      128
      >I
      JC     Err0                                            // kein Datenlistebereich

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

      L      1
      L      Stammdaten                                      // Anzahl der Stammdaten
      >I
      JC     Err0                                            // kein Datenlistebereich

      L      9
      >I
      JC     Err0                                            // kein Datenlistebereich

      L      Stammdaten                                      // Anzahl der Stammdaten
      L      Datensatzlaenge                                 // Datenblocklänge
      >I
      JC     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)

      OPN    DB[DBDatenliste]

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

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

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

      L      AnzahlEintraege                                 // Anzahl der eingetragenen Datensätze
      L      Listenlaenge                                    // Max.Anzahl von Datenblöcken
      >=I                                                    // Nein !
      JC     Err2                                            // Datenliste ist voll


--- NW 4: Indaten definiert ? ---

// In-DATEN-Pointer übernehmen:
      L      P#
      LAR2

      L      NoneW [AR2,]
      T      DBInDaten                                       // Indaten-DB

      L      DBInDaten                                       // Indaten-DB
      L      0                                               // Angegeben ?
      ==I                                                    // Nein
      JC     W401

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

CALL FC "TEST_DB_TO_ATTR_DB" (DB_Number:=DBInDaten, 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 !
      JC     Err4                                            // Undefinierte Indaten

      L      NoneD [AR2,]                                    // Kennung, Adresse
      L      16#00FF_FFFF                                    // Ohne Kennung
      AW
      SRW    3                                               // Ohne Bit
      T      InDaten_Startpunkt

      L      Datensatzlaenge                                 // Datenblocklänge
      L      2                                               // DB byteorientiert
      *I
      L      InDaten_Startpunkt
      +I
      L      SFC_DB_LENGTH
      >I                                                     // Indaten-DB ist zu kurz
      JC     Err4                                            // Undefinierte Indaten

W401: L      NoneD [AR2,]                                    // Kennung, Adresse
      T      InDaten_Pointer
      LAR2

      L      DBInDaten                                       // Indaten-DB
      L      0                                               // Angegeben ?
      ==I                                                    // Nein
      JC     W402

      OPN    DB[DBInDaten]

W402: L      NoneD [AR2,]                                    // Indaten überprüfen
      T      Sort_Daten                                      // 1.Indaten speichern

      L      Stammdaten
L400: T      Schleife

      L      DBInDaten                                       // Indaten-DB
      L      0                                               // Angegeben ?
      ==I                                                    // Nein
      JC     W403

      OPN    DB[DBInDaten]

W403: L      NoneW [AR2,]                                    // Indaten überprüfen
      L      0                                               // Etwas angegeben ?
      <>I                                                    // Ja !
      JC     Nw05                                            // Weiter

      ADDAR2 P#2.0

      L      Schleife
      LOOP   L400

      JU     Err4                                            // Undefinierte Indaten

Nw05: NOP 0


--- NW 5: Minimale + maximale Lesestelle am Anfang ---
      L      1
      T      Min_Lesestelle                                  // Minimal sinnvolle Lesestelle

      L      AnzahlEintraege                                 // Anzahl der eingetragenen Datensätze
      T      Max_Lesestelle                                  // Maximal sinnvolle Lesestelle

// Sonderfall: noch kein Eintrag: 
      L      0                                               // Eintrag schon vorhanden ?
      >I                                                     // Ja !
      JC     en05

      L      1                                               // An 1.Stelle speichern
      T      Savestelle                                      // Adresse

      JU     Save

en05: NOP 0


--- NW 6: Aktuelle Lesestelle errechnen ---
New:  L      Max_Lesestelle                                  // Maximal sinnvolle Lesestelle
      +      1
      L      Min_Lesestelle                                  // Minimal sinnvolle Lesestelle
      -I
      L      2
      /I
      L      Min_Lesestelle                                  // Minimal sinnvolle Lesestelle
      +I
      T      Lesestelle                                      // An dieser Stelle Datensatz lesen


--- NW 7: Daten an Lesestelle auslesen ---
      L      Lesestelle                                      // An dieser Stelle Datensatz lesen
      +      -1
      L      Datenblock_inBytes                              // Datenblocklänge in Bytes
      *I
      L      SSDW
      +I
      +      20                                              // Offset für 1.Daten
      ITD
      SLD    3
      T      AR1Zeiger                                       // /Statt AR1 (ging nur bis DB-Länge <= 8191 Bytes)

      OPN    DB[DBDatenliste]
      L      DBD [AR1Zeiger]                                 // Datenliste-Daten lesen
      T      Lese_Daten                                      // In Tabelle gelesenen Daten
      L      0                                               // Nichts gespeicher oder negativ ?
      <=D                                                    // Ja !
      JC     Err5


--- NW 8: Suche fertig ? ---
      L      Max_Lesestelle                                  // Maximal sinnvolle Lesestelle
      L      Min_Lesestelle                                  // Minimal sinnvolle Lesestelle
      -I
      L      0                                               // Suche fertig ?
      <I                                                     // Ja !
      JC     ok


--- NW 9: Gelesene Daten auswerten ---
      L      Sort_Daten                                      // Einzusortierende Daten
      L      Lese_Daten                                      // In Tabelle gelesenen Daten
      >D                                                     // Sort > Tabelle
      JC     MinP

      L      Sort_Daten                                      // Einzusortierende Daten
      >D                                                     // Tabelle > Sort
      JC     MaxM

      L      Lesestelle                                      // An dieser Stelle Datensatz lesen
      T      Savestelle                                      // An dieser Stelle wird In-Datensatz gespeichert

      JC     Frei                                            // Freiplatz schaffen

MinP: L      Lesestelle                                      // An dieser Stelle Datensatz lesen
      +      1
      T      Min_Lesestelle                                  // Minimal sinnvolle Lesestelle

      L      Max_Lesestelle                                  // Maximal sinnvolle Lesestelle
      >I                                                     // Suche ist fertig
      JC     ok

      JU     New

MaxM: L      Lesestelle                                      // An dieser Stelle Datensatz lesen
      +      -1
      T      Max_Lesestelle                                  // Maximal sinnvolle Lesestelle

      L      Min_Lesestelle                                  // Minimal sinnvolle Lesestelle
      <I                                                     // Suche ist fertig
      JC     ok

      JU     New


--- NW 10: Speicherstelle ermitteln ---
ok:   L      Sort_Daten                                      // Einzusortierende Daten
      L      Lese_Daten                                      // In Tabelle gelesenen Daten
      >D                                                     // Sort > Tabelle
      JC     Plus

      L      Lesestelle                                      // An dieser Stelle Datensatz lesen
      T      Savestelle                                      // An dieser Stelle wird In-Datensatz gespeichert

      JU     Frei                                            // Freiplatz schaffen

Plus: L      Lesestelle                                      // An dieser Stelle Datensatz lesen
      +      1
      T      Savestelle                                      // An dieser Stelle wird In-Datensatz gespeichert


--- NW 11: Freiraum für Speicherung schaffen ---
Frei: L      Savestelle                                      // An dieser Stelle wird In-Datensatz gespeichert
      T      "MW240"
      L      AnzahlEintraege                                 // Anzahl der eingetragenen Datensätze
      >I                                                     // Eintrag ans Ende !
      JC     Save

      L      AnzahlEintraege                                 // Anzahl der eingetragenen Datensätze
      L      Datenblock_inBytes                              // Datenblocklänge in Bytes
      *I
      L      SSDW
      +I
      +      20                                              // Offset für 1.Daten
      +      -2                                              // Letzte Daten letzter Eintrag
      T      Holstelle                                       // Freiraum schaffen: Stelle zum Daten holen

      L      Holstelle                                       // Freiraum schaffen: Stelle zum Daten holen
      L      Datenblock_inBytes                              // Datenblocklänge in Bytes
      +I
      T      Bringstelle                                     // Freiraum schaffen: Zeiger zum Daten schreiben

      L      AnzahlEintraege                                 // Anzahl der eingetragenen Datensätze
      L      Savestelle                                      // An dieser Stelle wird In-Datensatz gespeichert
      -I
      +      1
      L      Datenblock_inBytes                              // Datenblocklänge in Bytes
      *I
      L      2                                               // da DW-Zugriff (2Byte)
      /I
L110: T      Schleife

      L      Holstelle                                       // Freiraum schaffen: Stelle zum Daten holen
      ITD
      SLD    3
      T      Holzeiger                                       // Freiraum schaffen: Zeiger zum Daten holen
      L      Bringstelle                                     // Freiraum schaffen: Zeiger zum Daten schreiben
      ITD
      SLD    3
      T      Bringzeiger                                     // Freiraum schaffen: Zeiger zum Daten schreiben

      OPN    DB[DBDatenliste]

      L      DBW [Holzeiger]                                 // Datenliste-Daten lesen
      T      DBW [Bringzeiger]                               // Datenliste-Daten verschieben

      L      Holstelle
      +      -2                                              // 2 Byte wegen DW-Zugriff
      T      Holstelle                                       // Freiraum schaffen: Stelle zum Daten holen

      L      Bringstelle
      +      -2                                              // 2 Byte wegen DW-Zugriff
      T      Bringstelle                                     // Freiraum schaffen: Zeiger zum Daten schreiben

      L      Schleife
      LOOP   L110


--- NW 12: Daten in Datenliste schreiben ---
// Quelle-Pointer erzeugen:

Save: 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      Savestelle                                      // Adresse
      +      -1
      L      Datenblock_inBytes                              // Datenblocklänge in Bytes
      *I
      L      SSDW
      +I
      +      20                                              // Offset für 1.Daten
      SLD    3
      L      16#8400_0000                                    // Kennung: Daten
      OD
      T      LD16                                            // Kennung, Adresse

CALL SYS "BLKMOV" (SRCBLK:=Quelle, RET_VAL:=SFC_RET_VAL, DSTBLK:=Ziel)   // Datenliste-Daten speichern

      L      SFC_RET_VAL
      L      2#0000_0000_0000_0000
      <>I
      JC     Err1

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

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


--- NW 13: Fehlerausgabe / RET_VAL ---
      SET                                                    // VKE = 1 ohne Fehler !!!
      L      2#0000_0000_1000_0000                           // Daten wurden gespeichert
      JU     Ok_Mig
Err0: L      2#0000_0000_0000_0001                           // Kein Datenlistebereich
      JU     Err
Err1: L      2#0000_0000_0000_0010                           // SFC20-Aufruf mit Fehler
      JU     Err
Err2: L      2#0000_0000_0000_0100                           // Datenliste ist voll
      JU     Err
Err4: L      2#0000_0000_0001_0000                           // Undefinierte Indaten
      JU     Err
Err5: L      2#0000_0000_0010_0000                           // Gespeicherte Daten <= 0 (Inhalt ungültig)

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

Ok_Mig: T      RE_VAL
      SAVE                                                   // VKE in BIE-Bit speichern

      L      AR2_Speicher                                    // AR2 zurückspeichern
      LAR2

