{###########################################################################} procedure ParamToStr; var myNachkomma:byte; begin myNachkomma:=Nachkomma; if Nachkomma>7 then myNachkomma:=5; if abs(Param)>=10 then myNachkomma:=4; endif; if abs(Param)>=100 then myNachkomma:=3; endif; if abs(Param)>=1000 then myNachkomma:=2; endif; endif; if Param<>0 then ParamStr:=LongToStr(Param); else ParamStr:='0.00000'; setLength(ParamStr,myNachkomma+2); endif; end; procedure ParamLongToStr; //mit einer Nachkommastelle in Strin wandeln begin ParamStr:=LongToStr(ParamLong); end; procedure ParamLongToHex; //Longin in Hex-String wandeln begin ParamStr:=LongToHex(ParamLong); end; procedure ParamIntToHex; //Longin in Hex-String wandeln begin ParamStr:=IntToHex(ParamInt); end; procedure WriteParamStrSer; begin WriteChPrefix; write(SerOut, ParamStr); SerCRLF; end; procedure WriteParamSer; begin ParamToStr; WriteParamStrSer; end; procedure WriteParamIntSer; begin ParamStr:= IntToStr(ParamInt); WriteParamStrSer; end; procedure WriteParamByteSer; begin ParamStr:= ByteToStr(ParamByte); WriteParamStrSer; end; procedure WriteParamHexSer; // für verbose-Anfrage begin WriteChPrefix; write(SerOut, ParamStr); SerOut(#32); SerOut('['); SerOut('$'); ParamStr:= LongToHex(ParamLong); write(SerOut, ParamStr); SerOut(']'); SerCRLF; end; procedure WriteParamLongSer; begin ParamStr:= LongToStr(ParamLong); if hexmode then WriteParamHexSer; else WriteParamStrSer; endif; end; // gerätespezifischer Parser-Teil procedure ParseGetParam; var IntInOutFlag:boolean; myBranch:boolean; myByte:byte; myIndex:Byte; begin myIndex:=byte(SubCh mod 10); // angespr. Register 0..9 errechnen aus SubCh-Rest case SubCh of 0..63: FPGAreg:=byte(SubCh); SendFPGAreg; if (SubCh < 4) then FPGAsendLong:=ParamLongArray[SubCh]; // bei SPI-Lesen gesendeter Param retten endif; SendFPGA32; ParamLong:=FPGAreceiveLong; WriteParamLongSer; | 80: ParamByte:=ord(Modify); WriteParamByteSer; | 88: if hexmode then ParamByte:=1; else ParamByte:=0; endif; WriteParamByteSer; | 89: ParamByte:=byte(IncRast); WriteParamByteSer; | 128..131: // AutoInc-Register FPGAreg:=byte(SubCh); SendFPGAreg; SendFPGA32; ParamLong:=FPGAreceiveLong; WriteParamLongSer; | 240: WriteDirEntry; | 241: ClearDirectory; GetDirectory; FileNumTemp:=FileNum; if FileAnzahl>0 then for FileNum:= 0 to byte(FileAnzahl)-1 do FileNum:= i; WriteDirEntry; endfor; else FileNum:= 0; WriteDirEntry; endif; FileNum:=FileNumTemp; | 242: ParamByte:= byte(FileAnzahl); WriteParamByteSer; | 243: // DatFileName WriteChPrefix; write(SerOut,'0 ['+DatFileName+']'); SerCRLF; | 251: // Fehlerzähler auslesen ParamInt:=Errcount; WriteParamIntSer; | 253: // SerTest, gibt Input-String komplett und unverändert wieder aus write(SerOut, SerInpStr); SerCRLF; | 254: // Version WriteChPrefix; write(SerOut,Vers1Str); SerCRLF; | 250,255: // Status serprompt(NoErr); | else serprompt(ParamErr); endcase; end; procedure ParseSetParam; var myByte:byte; myIndex:Byte; myBranch:boolean; begin ChangedFlag:=true; myIndex:=byte(SubCh mod 10); // angespr. Register 0..9 errechnen aus SubCh-Rest case SubCh of 0..63: if (SubCh < 4) then ParamLongArray[SubCh]:=ParamLong; endif; FPGAreg:=byte(SubCh); SendFPGAreg; FPGAsendLong:=ParamLong; SendFPGA32; | 80: // LCD Anzeige-Wert Modify:=tModify(ParamByte); | 88: //Hex-Mode hexmode:= (ParamByte<>0); if EEunLocked then InitHexMode:=Hexmode; endif; | 128..131: // Default-Auto-Increment-Register FPGAreg:=byte(SubCh); SendFPGAreg; FPGAsendLong:=ParamLong; SendFPGA32; | 240: // CFG= if ParamAlpha then FileLoad(uppercase(ParamStr)); else FileNum:=ParamByte; FileLoad(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; | 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; | 253: // SerTest, gibt Input-String komplett und unverändert wieder aus write(SerOut, SerInpStr); SerCRLF; return; | 250: // EEPROM Write Enable | 280: //AutoIncrement-Register für DAT-Files AutoIncReg:= ParamByte; | 281: //AutoIncrement-Select (AUX-Select auf SubCh für DAT-Files AutoIncSel:= ParamByte; | 282: // Auto-Increment-Registerbreite im SPI, Anzahl Bytes (1, 2 oder 4) AutoIncWidth:=ParamByte; | 285: // Auto-Increment-Blockstart zum Speichern auf SD AutoIncBlockStart:=ParamLong; | 286: // Auto-Increment-Blockende zum Speichern auf SD AutoIncBlockEnd:=ParamLong; | else serprompt(ParamErr); return; endcase; EEunLocked:=false; if SubCh=250 then // EEPROM Write Enable EEunLocked:=true; endif; if verbose then serprompt(NoErr); endif; end; {###########################################################################} // Neuer Alpha-Parser, nimmt in ParamStr auch Strings nach "=" entgegen // allgemeiner Parser-Teil function Cmd2Index : byte; // 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 oder CmdStr 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:=SerInpStr[i]; if myChar in ['*'..'9'] then 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; begin Param:=StrToInt(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); ParamInt:=integer(ParamLong); ParamByte:=byte(ParamInt); end; procedure ParseSubCh; //Überprüfen, ob Befehl oder Daten eingegangen und für uns, Parser-Vorbehandlung, 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 isResult then if not INITfileIsOpen then WriteSerInp; endif; else if (not isOmni) and (CurrentCh<>MainCh) and hasMainCh then // nicht für uns WriteSerInp; return; endif; 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>0; // 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;