private static List<FunctionBlockRow> GetMC5Rows(byte[] code, int codestart, List<S5Parameter> parameters, Step5BlocksFolder blkFld, S5FunctionBlock block) { List<FunctionBlockRow> retVal=new List<FunctionBlockRow>(); int codepos = codestart; retVal.Add(new S5FunctionBlockRow() {Command = "BLD", Parameter = "255", Parent = block}); //Command for first Network does not exist! //This needs to be removen when written back to S5D! while (codepos < code.Length) { byte mc = code[codepos]; // finde Befehle in der Symbol Tabelle int index = find_mc5_code(code, codepos); S5FunctionBlockRow newRow = new S5FunctionBlockRow(){Parent = block}; if (index >= 0) { newRow.MC5LIB_SYMTAB_Row = (object[])sym[index]; bool fb = false; newRow.Command = (string) ((object[]) sym[index])[operation]; string oper = (string) ((object[]) sym[index])[operand]; if (oper == "PAR") { int paridx = find_mc5_param(code, codepos, index); if (parameters != null && parameters.Count > paridx - 1) { newRow.Parameter = "=" + parameters[paridx - 1].Name; } else { newRow.Parameter = "$$error$$ -> invalid Parameter, idx:"+ (paridx - 1); } } else { if (oper != null) newRow.Parameter = oper; fb = IsCall(newRow); //false; /*if ((newRow.Command=="SPA" && newRow.Parameter=="FB") || (newRow.Command=="SPB" && newRow.Parameter=="FB") || (newRow.Command=="BA" && newRow.Parameter=="FX") || (newRow.Command=="BAB" && newRow.Parameter=="FX")) { fb = true; }*/ int par = find_mc5_param(code, codepos, index); switch ((string)((object[])sym[index])[printpar]) { case null: break; case "PrintNummer": if (!string.IsNullOrEmpty(newRow.Parameter)) newRow.Parameter += " "; Int16 wrt =(Int16)par; if (wrt >= 0 && newRow.Parameter == "KF ") newRow.Parameter += " +"; newRow.Parameter += wrt.ToString(); break; case "PrintKY": newRow.Parameter += BitConverter.GetBytes(par)[1].ToString() + "," + BitConverter.GetBytes(par)[0].ToString(); break; case "PrintChar": if (!string.IsNullOrEmpty(newRow.Parameter)) newRow.Parameter += " "; newRow.Parameter += ((char)(BitConverter.GetBytes((Int16)par)[0])).ToString() + ((char)(BitConverter.GetBytes((Int16)par)[1])); break; case "PrintHEX4": if (!string.IsNullOrEmpty(newRow.Parameter)) newRow.Parameter += " "; newRow.Parameter += par.ToString("X").PadLeft(4, '0'); break; case "PrintGleitpunkt": if (!string.IsNullOrEmpty(newRow.Parameter)) newRow.Parameter += " "; newRow.Parameter += "gleit"; break; case "PrintHEX8": if (!string.IsNullOrEmpty(newRow.Parameter)) newRow.Parameter += " "; newRow.Parameter += par.ToString("X").PadLeft(4, '0'); break; case "PrintMerkerBit": if (!string.IsNullOrEmpty(newRow.Parameter)) newRow.Parameter += " "; newRow.Parameter += (par & 0x00FF).ToString() + "." + (par >> 8).ToString(); break; case "PrintSMerkerBit": if (!string.IsNullOrEmpty(newRow.Parameter)) newRow.Parameter += " "; newRow.Parameter += (par & 0x0FFF).ToString() + "." + (par >> 12).ToString(); break; } } int _parlen = (int)((object[])sym[index])[parlen]; int _codelen = (int)((object[])sym[index])[codelen]; int btSize = (_codelen + _parlen) / 8; codepos += btSize; // Schleifenzähler if (fb) { //FB-Call index = find_mc5_code(code, codepos); if (index < 0 || (string)((object[])sym[index])[operation] != "SPA=") newRow.Command = "Error reading Jump after FB/FX Call!"; int spa = find_mc5_param(code, codepos, index); newRow.ExtParameter=new List<S5Parameter>(); //newRow.ExtParameter = new List<string>(); byte[] calledfb = blkFld.GetBlockInByte("S5_" + newRow.Parameter.Replace(" ", "")); if (calledfb!=null) { S5Parameter newPar = new S5Parameter(); newRow.ExtParameter.Add(newPar); string fbNM = System.Text.Encoding.GetEncoding("ISO-8859-1").GetString(calledfb, 12, 8); //newRow.ExtParameter.Add("Name :" + fbNM); newPar.Name = "Name :"; newPar.Value = fbNM; List<S5Parameter> par = GetParameters(calledfb); int j = 0; foreach (var s5Parameter in par) { newPar = new S5Parameter(); newRow.ExtParameter.Add(newPar); j++; string akOper = ""; int pos = codepos + j*2; switch (s5Parameter.S5ParameterType) { case S5ParameterType.A: case S5ParameterType.E: int ber = code[pos]; switch (s5Parameter.S5ParameterFormat) { case S5ParameterFormat.BI: switch (ber & 0xf0) { case 0x80: akOper += "M"; break; } akOper += code[pos + 1].ToString(); akOper += "." + (code[pos] & 0x0f).ToString(); break; case S5ParameterFormat.BY: switch (ber) { case 0x0a: akOper += "MB"; break; case 0x2a: akOper += "DR"; break; case 0x22: akOper += "DL"; break; default: akOper += ""; break; } akOper += code[pos + 1].ToString(); break; case S5ParameterFormat.W: switch (ber) { case 0x12: akOper += "MW"; break; case 0x32: akOper += "DW"; break; } akOper += code[pos + 1].ToString(); break; case S5ParameterFormat.D: break; } break; case S5ParameterType.D: int wrt = code[pos]*0x100 + code[pos + 1]; akOper += s5Parameter.S5ParameterFormat.ToString() + " "; switch (s5Parameter.S5ParameterFormat) { case S5ParameterFormat.KF: if (((Int16)wrt)>0) akOper += "+"; akOper += ((Int16)wrt).ToString(); break; case S5ParameterFormat.KT: //code[pos + 1] // Bit 4-7 0-3 4-7 0-3 //Format: Zeitbasis, 100er, 10er, 1er akOper += wrt.ToString().PadLeft(3, '0') + ".0"; break; case S5ParameterFormat.KC: akOper += (char)code[pos] + (char)code[pos + 1]; break; case S5ParameterFormat.KM: akOper += libnodave.dec2bin(code[pos]) + " "; akOper += libnodave.dec2bin(code[pos + 1]); break; case S5ParameterFormat.KY: akOper += code[pos].ToString() + "," + code[pos + 1].ToString(); break; default: akOper += ((Int16)wrt).ToString("X").PadLeft(4, '0'); break; } break; case S5ParameterType.B: int bst = code[pos]; switch (bst) { case 0x20: akOper += "DB"; break; } akOper += code[pos + 1].ToString(); break; case S5ParameterType.T: //int abst = code[pos]; akOper += "T " + code[pos + 1].ToString(); break; case S5ParameterType.Z: akOper += "Z " + code[pos + 1].ToString(); break; } newPar.Name = s5Parameter.Name; newPar.Value = akOper; //newRow.ExtParameter.Add(s5Parameter.Name.PadRight(5, ' ') + ": " + akOper); } } else for (int j = 1; j < spa; j++) { int myPar = (code[codepos + j*2] << 8) | code[codepos + j*2 + 1]; //newRow.ExtParameter.Add(myPar.ToString()); S5Parameter newPar = new S5Parameter(); newRow.ExtParameter.Add(newPar); newPar.Name = myPar.ToString(); } btSize += spa * 2; codepos += spa * 2; fb = false; } byte[] MC5 = new byte[btSize]; Array.Copy(code,codepos - btSize, MC5, 0, btSize); newRow.MC5 = MC5; } else { newRow.Command = "Error converting command!"; codepos += 2; //throw new Exception("Code nicht in Symtab!"); } retVal.Add(newRow); } #region Build the Jumpsmarks.... int JumpCount = 1; int akBytePos = 0; Dictionary<int, S5FunctionBlockRow> ByteAdressNumerPLCFunctionBlocks = new Dictionary<int, S5FunctionBlockRow>(); foreach (S5FunctionBlockRow tmp in retVal) { if (tmp.ByteSize > 0) { ByteAdressNumerPLCFunctionBlocks.Add(akBytePos, tmp); akBytePos += tmp.ByteSize; } } akBytePos = 0; foreach (S5FunctionBlockRow tmp in retVal) { if (tmp.Command == "SPA=" || tmp.Command == "SPB=" || tmp.Command == "SPZ=" || tmp.Command == "SPN=" || tmp.Command == "SPP=" || tmp.Command == "SPM=" || tmp.Command == "SPO=") { int jmpBytePos = 0; byte[] backup = tmp.MC5; tmp.Command = tmp.Command.Substring(0, tmp.Command.Length - 1); tmp.JumpWidth = (SByte)Convert.ToInt32(tmp.Parameter); jmpBytePos = akBytePos + (tmp.JumpWidth * 2); if (ByteAdressNumerPLCFunctionBlocks.ContainsKey(jmpBytePos)) { var target = ByteAdressNumerPLCFunctionBlocks[jmpBytePos]; if (target.Label.Trim() == "") { target.Label = "M" + JumpCount.ToString().PadLeft(3, '0'); JumpCount++; } //Backup the MC7 Code, because the MC7 Code is always deleted when the command or parameter changes! tmp.Parameter = "=" + target.Label; tmp.MC5 = backup; } else { tmp.Parameter = "Error! JumpWidth :" + tmp.JumpWidth; tmp.MC5 = backup; } } akBytePos += tmp.ByteSize; } #endregion return retVal; }
public static S5FunctionBlock GetFunctionBlock(ProjectPlcBlockInfo blkInfo, byte[] block, byte[] preHeader, byte[] commentBlock, Step5ProgrammFolder prjBlkFld) { S5FunctionBlock retVal = new S5FunctionBlock(); retVal.BlockType = blkInfo.BlockType; retVal.BlockNumber = blkInfo.BlockNumber; if (blkInfo.BlockType == PLCBlockType.S5_PB || blkInfo.BlockType == PLCBlockType.S5_SB || blkInfo.BlockType == PLCBlockType.S5_OB) retVal.AWLCode = GetMC5Rows(block, 10, null, (Step5BlocksFolder) blkInfo.ParentFolder, retVal); else { string fbNM = System.Text.Encoding.GetEncoding("ISO-8859-1").GetString(block, 12, 8); retVal.Name = fbNM; List<S5Parameter> pars = GetParameters(block); retVal.Parameter = pars; retVal.AWLCode = GetMC5Rows(block, /*10 + spa*2*/ 10 + ((pars.Count*3) + 5)*2, pars, (Step5BlocksFolder) blkInfo.ParentFolder, retVal); } //Go throug retval and add Symbols... if (prjBlkFld != null) { if (prjBlkFld.SymbolTable != null) { foreach (S5FunctionBlockRow awlRow in retVal.AWLCode) { string para = awlRow.Parameter.Replace(" ", ""); awlRow.SymbolTableEntry = prjBlkFld.SymbolTable.GetEntryFromOperand(para); } } } retVal.Networks = new List<Network>(); S5FunctionBlockNetwork nw = null; if (retVal.AWLCode != null) foreach (S5FunctionBlockRow s5FunctionBlockRow in retVal.AWLCode) { if (s5FunctionBlockRow.Command == "BLD" && s5FunctionBlockRow.Parameter == "255") { if (nw != null) nw.AWLCode.Add(s5FunctionBlockRow); nw = new S5FunctionBlockNetwork(); nw.Parent = retVal; nw.AWLCode = new List<FunctionBlockRow>(); ((S5FunctionBlockNetwork) nw).NetworkFunctionBlockRow = s5FunctionBlockRow; retVal.Networks.Add(nw); } else { nw.AWLCode.Add(s5FunctionBlockRow); } } if (commentBlock != null) { int nr = 26; int netzwnr = 0; Dictionary<int, object> commandLineNumerList = new Dictionary<int, object>(); while (nr + 3 < commentBlock.Length) { int zeile = commentBlock[nr]; int len = 0x7f & commentBlock[nr + 2]; string cmt = System.Text.Encoding.GetEncoding("ISO-8859-1").GetString(commentBlock, nr + 3, len); if (commentBlock[nr + 1] == 0x00) { netzwnr = zeile; if (retVal.Networks.Count>netzwnr - 1 && netzwnr>0) { ((S5FunctionBlockNetwork) retVal.Networks[netzwnr - 1]).Name = cmt; commandLineNumerList.Clear(); int lineNr = 0; foreach (S5FunctionBlockRow akRow in retVal.Networks[netzwnr - 1].AWLCode) { commandLineNumerList.Add(lineNr, akRow); lineNr++; if (IsCall(akRow)) { foreach (S5Parameter extPar in akRow.ExtParameter) { commandLineNumerList.Add(lineNr, extPar); lineNr++; } } } } else { //Todo: Throw an error when this happens??? //throw new Exception("Error in Block: " + retVal.BlockName); } } else { if (commandLineNumerList.ContainsKey(zeile - 1)) { object obj = commandLineNumerList[zeile - 1]; if (obj is S5Parameter) ((S5Parameter) obj).Comment = cmt; else ((S5FunctionBlockRow) obj).Comment = cmt; } } nr += len + 3; } } return retVal; }
private string CreateHirachy(string prefix, S5FunctionBlock block, Stack<string> parentBlocks) { string spacer = " | "; parentBlocks.Push(block.BlockName); string retVal = ""; if (prefix != "") retVal += prefix.Substring(0, prefix.Length - 3) + "---" + block.BlockName + Environment.NewLine; else retVal += block.BlockName + Environment.NewLine; //foreach (var calledBlock in block.CalledBlocks) foreach (var calledBlock in block.CalledBlocks.Distinct()) { var fld = block.ParentFolder as Step5BlocksFolder; var blk = fld.GetBlock(calledBlock) as S5FunctionBlock; if (blk != null) { if (!parentBlocks.Contains(blk.BlockName)) { retVal += CreateHirachy(prefix + spacer, blk, parentBlocks); } else { retVal += prefix + spacer.Substring(0, 3) + "---" + blk.BlockName + " (recursive)" + Environment.NewLine; } } } parentBlocks.Pop(); return retVal; }