{###########################################################################}

// gerätespezifischer Parser-Teil
procedure ParseGetParam;
var IntInOutFlag:boolean;
    myBranch:boolean;
    myByte:byte;
    myIndex:Byte;
    SubChByte:byte;
    // myResponse:tresponseType; //(rNone, rByte, rInt, rFloat, rString, rStringInBrackets);
begin
  if Labelseek and (not (SubCh in [1000..1099])) then
    return; // nichts machen, wenn Label gesucht wird
  endif;
  IntInOutFlag:= (SubCh>=2000);
  if IntInOutFlag then  // Out-Befehl
    SubCh:=SubCh-2000;
  endif;
  SubChByte:=byte(SubCh);
  myIndex:=byte(SubCh mod 10);  // angespr. Register 0..9 errechnen aus SubCh-Rest
  case SubCh of
    8:
      GetFreqTimerString;
      WriteParamStrSer;
      |
    10..79,300..309: // VAL Eingangsspannung AD10, AD16
      if GetNewValue(SubCh) then
        WriteParamIntSer;
      else
        WriteParamSer;
      endif;
      |
    80:
      ParamByte:=ord(Modify);
      WriteParamByteSer;
      |
{$IFDEF EDIP}
    89:  // Display OK-Button, Sanduhr und warte auf drücken
      EDIPstr:=#27+'MN'+#201+#27+'MN'+#231;
      EDIPsend(DC1);
      myByte:=231;
      repeat
        CheckDelay(10);
        if LastMainPage=display then
          if isSysTimerzero(displayTimer) then
            EDIPstr:=#27+'MN'+char(myByte);
            EDIPsend(DC1);
            inctoLimWrap(myByte,238,231);
          endif;
          EDIPdisplayUpdate;
        endif;
      until ButtonPressed;
      repeat
        EDIPgetraw;
      until not ButtonPressed;
      LEDactivity:=high;
      serprompt(NoErr);
      |
{$ENDIF}
    90..95: // RTC
      GetRTC;
      ParamInt:=integer(RTCarray[myIndex]);
      WriteParamIntSer;
      |
    96: // Sync RTC, Stringausgabe Zeit
{$IFNDEF EXTDCF}
      GetExtRTC;
      SetRTC;
{$ENDIF}
      GetRTC;
      ParamByte:=0;
{$IFDEF EXTDCF}
      ParamByte:=DCFfield;
{$ENDIF}
      TimeToParamStr;
      WriteParamStrInBrackets(ParamByte);
      |
    97: // Sync RTC, Stringausgabe Datum
{$IFNDEF EXTDCF}
      GetExtRTC;
      SetRTC;
{$ENDIF}
      GetRTC;
      WriteChPrefix;
      ParamByte:=0;
{$IFDEF EXTDCF}
      ParamByte:=DCFfield;
{$ENDIF}
      DateToParamStr;
      WriteParamStrInBrackets(ParamByte);
      |
    98: // alle Eingangspegel Ports
      for SubCh:= 30 to 37 do
        GetNewValue(SubCh);
        WriteParamIntSer;
      endfor;
      |
    99: // alle Eingangspegel ADC
      for SubCh:= 10 to 17 do
        GetNewValue(SubCh);  // auf aktuellen Wert warten
        WriteParamSer;
      endfor;
      |
    100..107: // DEF 0 ADC Offset
      ParamInt:=ADCOffsets[myIndex];
      WriteParamIntSer;
      |
    110..117: // DEF 10 ADC Skalierung
      Param:=ADCScales[myIndex];
      WriteParamSer;
      |
    120..127: // DEF 20 DAC Offset
      ParamInt:=DACOffsets[myIndex];
      WriteParamIntSer;
      |
    130..137: // DEF 30 DAC Skalierung
      ParamFrac:=DACScales[myIndex];
      ParamFracToParam;
      WriteParamSer;
      |
    160..169: // DPC Display-SubChannel-Zuweisung
      ParamInt:=SubChArray[myIndex];
      WriteParamIntSer;
      |
    170..179: // BMX Bar-Maximalwert
      ParamInt:=BarMaxArray[myIndex];
      WriteParamIntSer;
      |
    200..209: // OPT
      ParamInt:=OptionArray[myIndex];
      WriteParamIntSer;
      |
    210:
      ParamStr:=EEinitFileName;
      WriteParamStrInBrackets(0);
      |
    211:
      ParamStr:=EEDatFileName;
      WriteParamStrInBrackets(0);
      |
    212: //Base-Skalierung ADC Wandler
      Param:=InitADCBaseScale;
      WriteParamSer;
      |
    213: //Base-Skalierung DAC Wandler
      Param:=Float(InitDACBaseScale);
      WriteParamSer;
      |
    230: //I2C generic byte
      TWIinp(I2CslaveAdr, ParamByte);
      WriteParamByteSer;
      |
    231: //I2C generic word
      TWIinp(I2CslaveAdr, ParamInt);
      WriteParamIntSer;
      |
    232: //I2C generic word swapped
      TWIinp(I2CslaveAdr, ParamInt);
      ParamInt:=swap(ParamInt);
      WriteParamIntSer;
      |
    233: //I2C LM75 scaled
      TWIinp(I2CslaveAdr, ParamInt);
      ParamInt:= swap(ParamInt) shr 7;
      Param:=float(ParamInt)/2;
      WriteParamSer;
      |
    239: //I2C generic Adr
      ParamInt:=Integer(I2CslaveAdr);
      WriteParamIntSer;
      |
    240:
      WriteDirEntry;
      |
    241:
      ClearDirectory;
      GetDirectory;
      FileNumTemp:=FileNum;
      if FileAnzahl>0 then
        for FileNum:= 0 to FileAnzahl-1 do
          WriteDirEntry;
        endfor;
      else
        FileNum:= 0;
        WriteDirEntry;
      endif;
      FileNum:=FileNumTemp;
      |
    242:
      ParamByte:=FileAnzahl;
      WriteParamByteSer;
      |
    243: // DatFileName
      ParamStr:=DatFileName;
      WriteParamStrInBrackets(0);
      |
    251: // Fehlerzähler auslesen
      ParamInt:=Errcount;
      WriteParamIntSer;
      |
    252: // Serielle Baudrate
      ParamByte:=EESerBaudReg;
      WriteParamByteSer;
      |
    253: // SerTest, gibt Input-String komplett und unverändert wieder aus
      write(mySerOut, SerInpStr);
      SerCRLF;
      |
    254: // Version
      WriteChPrefix;
      write(mySerOut,Vers1Str);
      SerCRLF;
      |
    250,255: // Status
      serprompt(NoErr);
      |

// Erweiterte SubCh für LabScript

    290: // Nächsten Stunden-Tick abwarten
      tickHours:=false;
      repeat
        Checkdelay(100);
      until tickHours or ButtonPressed;
      |
    291: // Nächsten Minuten-Tick abwarten
      tickMinutes:=false;
      repeat
        Checkdelay(100);
      until tickMinutes or ButtonPressed;
      |
    292: // Nächsten Sekunden-Tick abwarten
      tickSeconds:=false;
      repeat
        Checkdelay(10);
      until tickSeconds;
      |
    299: // letzter Pausenwert
      ParamInt:=integer(Pause);
      WriteParamIntSer;
      |
    320..329: // DEC
      Param:=RegisterArray[myIndex]-1;
      RegisterArray[myIndex]:=Param;
      CompareParam:=Param;
      |
    330..339: // INC
      Param:=RegisterArray[myIndex]+1;
      RegisterArray[myIndex]:=Param;
      CompareParam:=Param;
      |
    340..349: // CMP
      CompareParam:=RegisterArray[myIndex];
      |
    350..359: // XCH ohne Parameter, deshalb hier!
      Param:=RegisterArray[myIndex];
      RegisterArray[myIndex]:=AccA;
      AccA:=Param;
      |
    600..609: // MUL ohne Parameter, deshalb hier!
      Param:=AccA;
      AccA:=Param*RegisterArray[myIndex];
      |
    610..619: // DIV ohne Parameter, deshalb hier!
      Param:=AccA;
      AccA:=Param/RegisterArray[myIndex];
      |
    620..629: // ADD ohne Parameter, deshalb hier!
      Param:=AccA;
      AccA:=Param+RegisterArray[myIndex];
      |
    630..639: // SUB ohne Parameter, deshalb hier!
      Param:=AccA;
      AccA:=Param-RegisterArray[myIndex];
      |
    640..649: // SQR ohne Parameter, deshalb hier!
      Param:=RegisterArray[myIndex];
      RegisterArray[myIndex]:=sqrt(Param); // square root
      |
    650..659: // SQU ohne Parameter, deshalb hier!
      Param:=RegisterArray[myIndex];
      RegisterArray[myIndex]:=sqr(Param); // square root
      |
    660..669: // NEG ohne Parameter, deshalb hier!
      Param:=RegisterArray[myIndex];
      RegisterArray[myIndex]:=negate(Param); // square root
      |
    1000..1099: // LBL X, Label setzen, auch "if LabelSeek" oben beachten!
      if INITfileIsOpen then
        myByte:=byte(SubCh mod 100) and 31;
        if (CurrentGotoLabel=myByte) then // Label gefunden
          LabelSeek:=false;
        endif;
        LabelArray[myByte]:=word(F16_FilePos(InitFile)); // aktuelle Position
        LabelValidArray[myByte]:=true;             // gültiges Label
      endif;
      |
    1100..1699: // Goto/Branch für Script-Verarbeitung, SubCh = Label-Nummer
      if INITfileIsOpen then
        CurrentGotoLabel:=byte(SubCh mod 100) and 31;
        myBranch:=false;
        case SubCh of
        1100..1199:  // BRA, GTO
          myBranch:=true;
          |
        1200..1299:  // BRG
          if CompareParam > 0 then
            myBranch:=true;
          endif;
          |
        1300..1399:  // BGE
          if CompareParam >= 0 then
            myBranch:=true;
          endif;
          |
        1400..1499:  // BEQ
          if CompareParam = 0 then
            myBranch:=true;
          endif;
          |
        1500..1599:  // BLE
          if CompareParam <= 0 then
            myBranch:=true;
          endif;
          |
        1600..1699:  // BLE
          if CompareParam < 0 then
            myBranch:=true;
          endif;
          |
        endcase;
        if not LabelValidArray[CurrentGotoLabel] then // noch leer, also vorwärts
          LabelSeek:=myBranch; // aber nur, wenn Sprung
        else
          if myBranch then
            F16_FileSeek(InitFile,longword(LabelArray[CurrentGotoLabel])); // Label aufsuchen
          endif;
        endif;
      endif;
      |
  else
    serprompt(ParamErr);
    return;
  endcase;
end;

{###########################################################################}

procedure ParseSetParam;
var myIndex:Byte;
    SubChByte:byte;

begin
  if Labelseek then
    return; // nichts machen, wenn Label gesucht wird
  endif;
  ChangedFlag:=true;
  if SubCh>=2000 then  // RIO-Befehl
    Param:=RegisterArray[Parambyte];
    SubCh:=SubCh-2000;
    ParamLong:=LongInt(Param);
    ParamInt:=integer(ParamLong);
    ParamByte:=byte(ParamInt);
  endif;
  SubChByte:=byte(SubCh);
  ParamToParamFrac;  // falls benötigt
  myIndex:=byte(SubCh mod 10);  // angespr. Register 0..9 errechnen aus SubCh-Rest
  case SubCh of
    9:
      SetFreqMeasureMode(ParamByte);
      |
    20..27: //Wert
      SetDACfrac(myIndex,ParamFrac);
      if EEunLocked then
        InitDACValueArray[myIndex]:=Param;
      endif;
      |
    30..37: //PIO IO-Pins
      SetPort(myIndex,Parambyte);
      if EEunLocked then
        InitPortArray[myIndex]:=Parambyte;
      endif;
      |
    40..47: //DDR IO-Pins, INIT-Array bei WEN=1 ändern!
      SetDir(myIndex,Parambyte);
      if EEunLocked then
        InitDDRArray[myIndex]:=Parambyte;
      endif;
      |
    80: // LCD Anzeige-Wert
      ModifySema:=true;
      if ParamByte > 9 then
        serprompt(ParamErr);
        return;
      endif;
      Modify:=ParamByte;
      |
    81: // LCD Mainpage
      DisplaySwitchSema:=true;
      if ParamByte > 3 then
        serprompt(ParamErr);
        return;
      endif;
      MainPage:=tPage(ParamByte);
      |
    82: // LCD Subselect
      SubSelectSema:=true;
      SubSelect:=ParamByte;
      |
    83: // LCD Increment/Decrement
      IncrSema:=true;
      IncrDiff:=ParamInt;
      |
    84: // LCD Button
      ButtonSelectSema:=true;
      ButtonSelect:=ParamByte;
      |
    86: // Parameter-Stellen
      digits:=ParamByte;
      if EEunLocked then
        InitDigits:=ParamInt;
      endif;
      |
{
    88:
      IntegrateAD16:=(ParamByte<>0);
      if EEunLocked then
        InitIntegrateAD16:=IntegrateAD16;
      endif;
      |
}
    90..95: // CLK-Funktionen
      GetRTC;
      RTCarray[myIndex]:=ParamByte;
      SetRTC;
{$IFDEF EXTRTC}
      SetExtRTC;
{$ENDIF}
      |
    100..107:
      ADCOffsets[myIndex]:=ParamInt;
      if EEunLocked then
        InitADCOffsetArray[myIndex]:=ParamInt;
      endif;
      |
    110..117:
      ADCScales[myIndex]:=Param;
      if EEunLocked then
        InitADCScaleArray[myIndex]:=Param;
      endif;
      |
    120..127:
      DACOffsets[myIndex]:=ParamInt;
      if EEunLocked then
        InitDACOffsetArray[myIndex]:=ParamInt;
      endif;
      |
    130..137:
      DACScales[myIndex]:=ParamFrac;
      if EEunLocked then
        InitDACScaleArray[myIndex]:=Param;
      endif;
      |
    160..169:
      SubChArray[myIndex]:=ParamInt;
      ModifySema:=true; // Neuanzeige erzwingen
      SetSysTimer(DisplayTimer,0);  // Update erzwingen
      if EEunLocked then
        InitSubChArray[myIndex]:=ParamInt;
      endif;
      |
    170..179:
      BarMaxArray[myIndex]:=ParamInt;
      ModifySema:=true; // Neuanzeige erzwingen
      SetSysTimer(DisplayTimer,0);  // Update erzwingen
      if EEunLocked then
        InitBarMaxArray[myIndex]:=ParamInt;
      endif;
      |
    180..189: // LCD Anzeige-Text DPT="text"
      if ParamAlpha then
        ParamTextArray[SubCh-180]:=ParamStr;
        if EEunLocked then
          ParamTextArray[SubCh-180]:=ParamStr;
        endif;
        ModifySema:=true; // Neuanzeige erzwingen
        SetSysTimer(DisplayTimer,0);  // Update erzwingen
      else
        serprompt(ParamErr);
        return;
      endif;
      |
    190..199: // LCD Anzeige Einheit DPU
      if ParamAlpha then
        UnitArray[SubCh-180]:=ParamStr;
        if EEunLocked then
          InitUnitArray[SubCh-180]:=ParamStr;
        endif;
        ModifySema:=true; // Neuanzeige erzwingen
        SetSysTimer(DisplayTimer,0);  // Update erzwingen
      else
        serprompt(ParamErr);
        return;
      endif;
      |
    200..209:
      if EEunLocked then
        OptionArray[myIndex]:=ParamInt;
        mdelay(3);
        InitVars;
      else
        serprompt(LockedErr);
        return;
      endif;
      |
    210,211:
      if EEunLocked then
        if ParamAlpha then
          if SubCh = 210 then
            EEInitFileName:=uppercase(ParamStr); //210
          else
            EEdatFileName:=uppercase(ParamStr); // 211
          endif;
        else
          serprompt(ParamErr);
          return;
        endif;
      endif;
      |
    212,213: //Base-Skalierung ADC,DAC Wandler
      if EEunLocked then
        if SubCh = 212 then
          InitADCBaseScale:=Param;
        else
          InitDACBaseScale:=ParamLong; // 213=DACBaseScale
        endif;
        InitVars;
      else
        serprompt(LockedErr);
        return;
      endif;
      |
    240:  // CFG=
      if ParamAlpha then
        FileName:=uppercase(ParamStr);
      else
        FileNum:=ParamByte;
        FileName:=DirectoryArray[FileNum];
      endif;
      if FaultFlags<>0 then
        serprompt(FileErr);
        return;
      endif;
      |
    243:  // DatFileName, FNA=
      if ParamAlpha then
        DatFileName:=uppercase(ParamStr);
      else
        FileNum:=ParamByte;
        DatFileName:=DirectoryArray[FileNum];
      endif;
      if FaultFlags<>0 then
        serprompt(FileErr);
        return;
      endif;
      |
    244:  // Delete, FDL=
      if ParamAlpha then
        SerInpStr:=uppercase(ParamStr);
      else
        FileNum:=ParamByte;
        SerInpStr:=DirectoryArray[FileNum];
      endif;
      if CardOK then
        if not F16_FileDelete ('\', SerInpStr) then
          ReadErr:=true;
          WriteErr:=true;
          serprompt(FileErr);
          return;
        endif;
      else
        serprompt(FileErr);
        return;
      endif;
      |
    249:  // FileExists
      if ParamAlpha then
        SerInpStr:=uppercase(ParamStr);
      else
        FileNum:=ParamByte;
        SerInpStr:=DirectoryArray[FileNum];
      endif;
      if CardOK and F16_FileExist ('\', SerInpStr, faFilesOnly) then
        FaultFlags:=0;
        serprompt(noErr);
        return;
      else
        ReadErr:=true;
        serprompt(FileErr);
        return;
      endif;
      |
    251: //Error-Count
      ErrCount:=ParamInt;
      |
    252: // Serielle Baudrate, erst beim nächsten Reset aktiv
      if EEunLocked then
        EESerBaudReg:=ParamByte;
      else
        serprompt(LockedErr);
        return;
      endif;
      |
    253: // SerTest, gibt Input-String komplett und unverändert wieder aus
      write(mySerOut, SerInpStr);
      SerCRLF;
      return;
      |
    250: // EEPROM Write Enable
      |

// Erweiterte SubCh für LabScript

    260..269: // FWR FileWrite Registerwert in DataFile
      DataWrite(ParamByte,true);
      |
    270..279: // FWV FileWrite Parameter in DataFile
      DataWrite(myIndex,false);
      |

    299: //Pause für Script-Verarbeitung, Wert in ms
      Pause:=word(ParamInt);
      if Pause>0 then
        mdelay(Pause);
      endif;
      |
    300..309: // REG, LDA, LDB
      RegisterArray[myIndex]:=Param;
      |
    310..319: // MOV
      Param:=RegisterArray[ParamByte];
      RegisterArray[myIndex]:=Param;
      |
    350..359: // XCH mit Parameter, zwei beliebige Register tauschen
      if ParamByte in [0..9] then
        Param:=RegisterArray[ParamByte];
        RegisterArray[ParamByte]:= RegisterArray[myIndex];
        RegisterArray[myIndex]:=Param;
      endif;
      |
   else
    serprompt(ParamErr);
    return;
  endcase;
  EEunLocked:=false;
  if SubCh=250 then  // EEPROM Write Enable
    EEunLocked:=true;
  endif;
  if CheckLimits then
    serprompt(ParamErr);
  else
    if verbose then
      serprompt(NoErr);
    endif;
  endif;
end;

{###########################################################################}
// Neuer Alpha-Parser, nimmt in ParamStr auch Strings nach "=" entgegen

// allgemeiner Parser-Teil


function Cmd2Index : byte;
// Lookup, Umsetzen eines Text-Befehls in Index-Eintrag der Befehlstabelle
var myCmdIndex: byte;
begin
  ParamStr:= uppercase(ParamStr);
  for myCmdIndex := 0 to CmdAnzahl do
    if ParamStr = CmdStrArr[ord(myCmdIndex)] then
      return(myCmdIndex);
    endif;
  endfor;
  return(cmderr);
end;

function ParseExtract(nachGleich:boolean):boolean;
//extrahiert ParamStr aus SerInpStr,
//liefert true, wenn Parameter, sonst false, wenn Command
//akzeptiert auch alphanumerische Parameter als String nach "="
var myChar: char; myBool:boolean;
begin
  ParamStr:='';
  ParamAlpha:=false;
  myBool:=false;
  while SerInpStr[SerInpPtr] =' ' do // Leerzeichen überspringen
    inc(serInpPtr);
  endwhile;
  if SerInpStr[SerInpPtr] in ['%'..'9'] then // Zahlen oder Wildcard, es wird ein Parameter
    myBool:=true;
    for i:=SerInpPtr to length(SerInpStr) do
      mychar:=upcase(SerInpStr[i]);
      if myChar in ['%'..'9','A'..'F'] then
        if mychar='&' then   // HEX-Zeichen
          mychar:='$';   // für StrToInt "übersetzen"
        endif;
        append(mychar,ParamStr);
      else // Buchstabe oder sonstirgendwas, abbrechen
        SerInpPtr:=i;
        return(mybool);
      endif;
    endfor;
  else
    for i:=SerInpPtr to length(SerInpStr) do
      mychar:=SerInpStr[i];
      if mychar='"' then
        ParamAlpha:=true;
      else
        if (mychar>='A') or ParamAlpha then
          if (myChar in ['!','?','$']) then
            SerInpPtr:=i;
            return(mybool);
          else
            append(mychar,ParamStr);
          endif;
          if nachGleich then
            ParamAlpha:=true;
          endif;
        else // Ziffer oder sonstirgendwas, abbrechen
          SerInpPtr:=i;
          return(mybool);
        endif;
      endif;
    endfor;
  endif;
  return(mybool);
end;

procedure ParamStr2Param;
var DecPointPos:byte; mylen:byte; mychar:char;
begin
  mychar:=ParamStr[1];
  ParamLong:=StrToInt(ParamStr);
  if mychar='%' then // Binärwert in Long wandeln
    ParamLong:=0;
    mylen:=length(ParamStr);
    for i:=mylen downto 2 do
      if ParamStr[i]='1' then
        incl(ParamLong,mylen-i);
      endif;
    endfor;
    Param:=Float(ParamLong);
  elsif mychar<>'$' then
    Param:=StrToFloat(ParamStr);
  // 32-Bit-Werte passen nicht in ein Float, deshalb getrennt wandeln
    DecPointPos:= pos('.',ParamStr);
  // vor Dezimalpunkt abschneiden
    if DecPointPos>0 then
      SetLength (ParamStr,DecPointPos-1);
    endif;
    ParamLong:=StrToInt(ParamStr);
  endif;
  ParamInt:=integer(ParamLong);
  ParamByte:=byte(ParamInt);
end;


procedure ParseSubCh;
//Überprüfen, ob Befehl oder Daten eingegangen und für uns, Parser-Vorbehandlung,
//Achtung: Erweitert um ParseResult für Anzeige-Auswertung, KEIN REFERENZ-PARSER!

var
  GleichPos,
  CheckSpos, myCheckSum,CheckSumIn:byte;
  SubChOffset:integer;

  myChar:char;
  hasMainCh, hasCRC, isResult, isOmni, isRequest: Boolean;

begin
  if SerInpStr='' then
    serprompt(NoErr);
    return;
  endif;
  hasMainCh:=(pos(':',SerInpStr)>0); // Kanaltrenner-':'
  gleichPos:=pos('=',SerInpStr); // Set-'='
  isRequest:=(GleichPos=0); // Abfrage
  myChar:=SerInpStr[1];
  isOmni:=(myChar='*');    // Omni-Flag
  isResult:=(myChar='#');  // Ergebnis-'#'
  SerInpPtr:=1;
  if isResult then
    SerInpPtr:=2;
  endif;
  if hasMainCh then
    ParseExtract(false);
    inc(SerInpPtr);
    if isOmni then // Omni-Befehl
      WriteSerInp; // weiterleiten
    else
      CurrentCh:=StrToInt(ParamStr);
    endif;
  endif;
  if (not isOmni) and (CurrentCh<>MainCh) and hasMainCh then // nicht für uns
    WriteSerInp;
    return;
  endif;

// Befehl/Parameter ist für uns, ab hier eigentliche Behandlung
// Wenn vorhanden, XOR-Prüfsumme checken, Präfix-"$" zählt nicht mit!
  verbose:=(pos('!',SerInpStr)>0) OR (pos('?',SerInpStr)>0); // Ausführliche Antwort erwünscht

  CheckSpos:=pos('$',SerInpStr);
  hasCRC:=CheckSpos>(gleichPos+1); // CheckSumIn-'$'

  if hasCRC then
    ParamStr:=copy(SerInpStr,CheckSpos+1, 2);
    CheckSumIn:=HexToInt(ParamStr); // erhaltene XOR-Checksumme
    myCheckSum:=0;
    for i:= 1 to CheckSpos-1 do
      myChar:=SerInpStr[i];
      myCheckSum:=myCheckSum xor ord(myChar);
    endfor;
    if myCheckSum <> CheckSumIn then
      serprompt(CheckSumErr);
      return;
    endif;
  endif;

//  SerInpStr:=trim(SerInpStr);

//Parse einzelnen Befehl
  if ParseExtract(false) then
    SubChOffset:=0; // direkter SubCh-Aufruf
  else
    CmdWhich:=Cmd2Index; // Klartext übersetzen
    if CmdWhich = cmderr then
      serprompt(SyntaxErr);
      return;
    endif;
    SubChOffset:=Cmd2SubChArr[ord(CmdWhich)];
    ParseExtract(false); // SubCh-Parameter holen
  endif;
  SubCh:=StrToInt(ParamStr)+SubChOffset; //auf neuen SubCh umrechnen
  if isRequest then
    ParseGetParam;
  else
    SerInpPtr:=gleichPos+1; // Set-'='
    if ParseExtract(true) then
      ParamStr2Param;
    else
      Param:=0;             // evt. auch Alpha-Parameter
      ParamLong:=0;
      ParamInt:=0;
      ParamByte:=0;
    endif;
    ParseSetParam;
  endif;
end;

