procedure ParseInpStr;
{
normale Syntax: (alle auch mit <*> vorweg als Omni-Befehl)
1. Typ:
CMD <SPACE> <MainCh> <:> <SubCh> <=> <Wert> <CRLF>
2. Typ: (noch nicht implementiert)
CMD <SPACE> <MainCh> <:> <SubCh> <-> <SubCh> <=> <Wert> <CRLF> (Kanal von...bis)
3. Typ:
CMD <SPACE> <SubCh> <?> <CRLF>
4. Typ:
CMD <SPACE> <SubCh> <-> <SubCh> <?> <CRLF> (Kanal von...bis)
Ein-Paramater-Befehle:
5. Typ:
CMD <SPACE> <SubCh> <CRLF>
Null-Paramater-Befehle:
6. Typ:
CMD <CRLF>

Kurzform: VAL <SPACE> und <MainCh> <:> können weggelassen werden,
es wird dann der zuletzt angesprochene Kanal verwendet
Beispiel:
VAL 0:5?
0:5?
5?
VAL 0:20=1.00
0:20=1.00
20=1.00

}

var
  ParamStr:string[40]; // auch für Display
  Request:boolean;
  ParamInt1, ParamInt2:Integer;
  Laenge, ParamStartPos, BisPos, GleichPos, FragePos,DpunktPos,
  SubChStart,SubChEnd:byte;
  firstChar:char;

begin
  SerInpStr:=trim(SerInpStr);
  FirstChar:=SerInpStr[1];
  if FirstChar='*' then // Omni-Befehl
    WriteSerInp; // weiterleiten
    OmniFlag:=true;
    delete(SerInpStr,1,1);
    FirstChar:=SerInpStr[1];
  else
    OmniFlag:=false;
  endif;
//Parse einzelnen Befehl
  CmdStr:=copy(SerInpStr,1,3);
  CmdWhich:=Cmd2Index;

  ParamStartPos:=pos(' ',SerInpStr)+1; // Trenner-' '

  if FirstChar <'A' then // Kurzbefehl statt "VAL"
    ParamStartPos:=1;
    CmdWhich:=val;
  endif;

  DpunktPos:=pos(':',SerInpStr); // Kanaltrenner-':'
  FragePos:=pos('?',SerInpStr); // Request-'?'
  GleichPos:=pos('=',SerInpStr); // Set-'='
  BisPos:=pos('-',SerInpStr); // Bis-'-'?
  Laenge:=length(SerInpStr);

  if DpunktPos > 0 then
    ParamStr:=copy(SerInpStr,ParamStartPos,(DpunktPos-ParamStartPos));
    CurrentCh:=StrToInt(ParamStr); // neuer Kanal
    ParamStartPos:= DpunktPos+1;
  endif;

  if (not OmniFlag) and (CurrentCh<>MyChannel) then // nicht für uns
    WriteSerInp;
    return;
  endif;
  if FirstChar='#' then // Messwert
    WriteSerInp;
    return;
  endif;
  if length(SerInpStr) = 0 then
    serprompt(NoErr);
    return;
  endif;

  if FragePos > 0 then
    Request:=true;
    dec(Laenge); // ohne Fragezeichen
    SerInpStr:=copy(SerInpStr,1,Laenge);
  else
    if BisPos > GleichPos then
      BisPos:=0; // Minuszeichen im Wert, nicht berücksichtigen
    endif;
    Request:=false;
  endif;

  if BisPos > 0 then
    ParamStr:=copy(SerInpStr,ParamStartPos,(BisPos-ParamStartPos));
    ParamInt1:=StrToInt(ParamStr); // von
    ParamStr:=copy(SerInpStr,BisPos+1,Laenge);
    ParamInt2:=StrToInt(ParamStr); // bis
    SubChStart:=byte(ParamInt1);
    SubChEnd:=byte(ParamInt2);
    if SubChEnd<SubChStart then
      serprompt(ParamErr);
      return;
    endif;
  else
    ParamStr:=copy(SerInpStr,ParamStartPos,(GleichPos-ParamStartPos));
    ParamInt1:=StrToInt(ParamStr);
    SubChStart:=byte(ParamInt1);
    SubChEnd:=SubChStart;
  endif;


  if CmdWhich = err then
    serprompt(SyntaxErr);
    return;
  endif;

  if not Request then
    if CmdWhich >= val then // Befehle mit 2 Parametern auswerten
      if (GleichPos=0) or (GleichPos=Laenge) then // '=' fehlt
        serprompt(SyntaxErr);
        return;
      endif;
    else // einen Byte- oder keinen Parameter
      SubCh:=0;
    endif;
    ParamStr:=copy(SerInpStr,GleichPos+1,Laenge);
    Param:=StrToFloat(ParamStr);
    ParamInt2:=integer(Param);
    ParamByte:=byte(ParamInt2);
    SubCh:=byte(ParamInt1);
  endif;

  SubCh:=byte(ParamInt1);

  if request then
  // SubCh-Start in ParamInt1, SubCh-Ende in ParamInt2
    case CmdWhich of
      idn: //Wert
        SubCh:=ErrSubCh;
        WriteChPrefix;
        write(serout,Vers1Str);
        writeFeatures(false);
        SerCRLF;
        return;
        |
      val: //Wert
        case SubChStart of
          0..7:
            getAD10;  // auf aktuellen Wert warten
          |
          10..17:
            getAD16;  // auf aktuellen Wert warten
          |
        endcase;
        if (SubChEnd-SubChStart)>7 then
            getAD24;  // auf aktuellen Wert warten
        else
          if SubChStart in [8,9] then
            getAD24;  // auf aktuellen Wert warten
          endif;
        endif;
        for SubCh:= SubChStart to SubChEnd do
          WriteChPrefix;
          Param:=ValueArray[SubCh];
          WriteParam(false);
        endfor;
        |
      scl: //Skalierung
        for i:= SubChStart to SubChEnd do
          WriteChPrefix;
          Param:=ScaleArray[i];
          WriteParam(false);
        endfor;
        |
      ofs: //Offset
        for i:= SubChStart to SubChEnd do
          WriteChPrefix;
          ParamInt:=OffsetArray[i];
          WriteParamInt(false);
        endfor;
        |
      dir: //Offset
        for i:= SubChStart to SubChEnd do
          WriteChPrefix;
          ParamInt:=integer(DirArray[i]);
          WriteParamInt(false);
        endfor;
        |
      inp: //Input Port
        getPorts;
        for i:= SubChStart to SubChEnd do
          WriteChPrefix;
          ParamInt:=integer(PinArray[i]);
          WriteParamInt(false);
        endfor;
        |
      out: //Output Port
        for i:= SubChStart to SubChEnd do
          WriteChPrefix;
          ParamInt:=integer(PortArray[i]);
          WriteParamInt(false);
        endfor;
        |
      raw: //Hex-Wert roh
        WriteChPrefix;
        case SubCh of
          0..7:
            getAD10;  // auf aktuellen Wert warten
            write(serout,inttostr(AD10array[SubCh]));
          |
          10..17:
            getAD16;  // auf aktuellen Wert warten
            write(serout,inttostr(AD16array[SubCh-10]));
          |
          8:
            getAD24;  // auf aktuellen Wert warten
            write(serout,longtostr(AD24_1));
          |
          9:
            getAD24;  // auf aktuellen Wert warten
            write(serout,longtostr(AD24_2));
          |
        endcase;
        SerCRLF;
        return;
        |
    else
      serprompt(SyntaxErr);
      return;
    endcase;
  else  // kein Request, also Parameter setzen
    case CmdWhich of
      val: //Wert
        ValueArray[SubCh]:=Param;
        SetDAC(SubCh);
        |
      dsp: //String auf Display
        if LCDpresent then
          x:=SubCh mod 20;
          y:=SubCh div 20;
          LCD1xy;
          write(lcdout_m, ParamStr);
        endif;
        |
      dlv: //Wert in SubCh auf Display, nonvolatile
        if LCDpresent and (SubCh<4) then
          LCDTalkArray[SubCh]:=byte(ParamInt2);
          x:=0;
          y:=SubCh;
          LCD1xy;
          LCDclreol_M(LCD_m1);
        else
          serprompt(ParamErr);
          return;
        endif;
        |
      dlt: //String (SubCh) auf Display, nonvolatile
        if LCDpresent and (SubCh<4) then
          LCDTextArray[SubCh]:=ParamStr;
          x:=0;
          y:=SubCh;
          LCD1xy;
          LCDclreol_M(LCD_m1);
        else
          serprompt(ParamErr);
          return;
        endif;
        |
      scl: //Skalierung
        ScaleArray[SubCh]:=Param;
        SetDAC(SubCh);
        |
      ofs: //Offset
        OffsetArray[SubCh]:=ParamInt2;
        SetDAC(SubCh);
        |
      dir: //DDR IO-Pins
        if (SubCh < 7) then
          DirArray[SubCh]:=Parambyte;
          SetDir;
        else
          serprompt(ParamErr);
          return;
        endif;
        |
      out: //Output IO-Pins
        if (SubCh < 7) then
          PortArray[SubCh]:=Parambyte;
          SetPorts;
        else
          serprompt(ParamErr);
          return;
        endif;
        |
      tlk: //Talk
        Talkarray[SubCh]:= not (Parambyte=0);
        |
      tim: //Timing Talk
        TalkTiming:= word(ParamInt1);
        |
      chn: //Empfangskanal
        CurrentCh:= byte(ParamInt1);
        |
      zer: //Zero Channel
        SubCh:=byte(ParamInt1); //Parameter ist SubChannel
        if SubCh in [0..7] then
          getAD10;  // auf aktuellen Wert warten
          OffsetArray[SubCh]:=-(AD10array[SubCh]);
        endif;
        if SubCh in [10..17] then
          getAD16;  // auf aktuellen Wert warten
          OffsetArray[SubCh]:=-(AD16array[SubCh-10]);
        endif;
        if SubCh = 8 then
          getAD24;  // auf aktuellen Wert warten
          OffsetArray[SubCh]:=-integer(AD24_1);
        endif;
        if SubCh = 9 then
          getAD24;  // auf aktuellen Wert warten
          OffsetArray[SubCh]:=-integer(AD24_2);
        endif;
        |
    else
      serprompt(SyntaxErr);
      return;
    endcase;
    serprompt(NoErr);
  endif;
end;

