Exemple #1
0
        /// <summary>
        /// Generate code from pinout
        /// </summary>
        /// <param name="pins"></param>
        /// <param name="codeBuffer"></param>
        internal static void CompilePinout(IEnumerable <LDPin> pins, CompilerBuffer codeBuffer)
        {
            if (pins.Count(x => x.Pin == "NONE") > 0)
            {
                throw new InvalidOperationException("Can't Compile with unassigned pins in diagram");
            }

            codeBuffer.SetupContent.Add("//Inputs");
            foreach (var pin in pins.Where(x => x.Type == PinType.Input))
            {
                codeBuffer.SetupContent.Add("pinMode(" + pin.Pin + ", INPUT);//" + pin.Variable);
                codeBuffer.InputRefreshContent.Add(pin.Variable + " = digitalRead(" + pin.Pin + ");");
            }

            foreach (var pin in pins.Where(x => x.Type == PinType.Analog))
            {
                codeBuffer.SetupContent.Add("//Pin " + pin.Pin + " used as analog input to " + pin.Variable);
                codeBuffer.Defines.Add("#define " + pin.Variable + " " + pin.Pin + " //Analog input pin");
            }


            codeBuffer.SetupContent.Add("//Outputs");
            foreach (var pin in pins.Where(x => x.Type == PinType.Output))
            {
                codeBuffer.SetupContent.Add("pinMode(" + pin.Pin + ", OUTPUT);//" + pin.Variable);
                codeBuffer.OutputRefreshContent.Add("digitalWrite(" + pin.Pin + ", " + pin.Variable + ");");
            }
            foreach (var pin in pins.Where(x => x.Type == PinType.PWM))
            {
                codeBuffer.SetupContent.Add("pinMode(" + pin.Pin + ", OUTPUT);//PWM to " + pin.Variable);
                codeBuffer.Defines.Add("#define " + pin.Variable + " " + pin.Pin + " //PWM pin");
            }
        }
Exemple #2
0
        /// <summary>
        /// Compile a Ladder Diagram to Arduino C++
        /// </summary>
        /// <param name="diagram"></param>
        /// <returns></returns>
        public static string CompileDiagram(Diagram diagram)
        {
            if (diagram == null)
            {
                throw new ArgumentNullException("diagram", "Null Diagram");
            }

            CompilerBuffer codeBuffer = new CompilerBuffer();

            CompileDataTable(diagram.DataTable, codeBuffer);
            CompilePinout(diagram.Pins, codeBuffer);
            CompileRungs(diagram.Rungs, codeBuffer);

            return(CodeBuilder(codeBuffer));
        }
Exemple #3
0
        /// <summary>
        /// Compile single input function
        /// </summary>
        /// <param name="component">Component to be compiled</param>
        /// <param name="input">Function logical input</param>
        /// <param name="codeBuffer">Compiler's code buffer</param>
        /// <returns></returns>
        internal static string CompileInputFunctionComponent(ComponentBase component, string input, CompilerBuffer codeBuffer)
        {
            string buffer = string.Empty;

            if (component is OSF)
            {
                buffer = OSF_FN + "(" + codeBuffer.OSRCount + ", " + input + ")";
                codeBuffer.OSFCount++;
            }
            else if (component is OSR)
            {
                buffer = OSR_FN + "(" + codeBuffer.OSRCount + ", " + input + ")";
                codeBuffer.OSRCount++;
            }
            else if (component is CounterComponent)
            {
                CounterComponent counter = component as CounterComponent;

                if (component is CTD)
                {
                    buffer = CTD_FN + "(" + counter.Limit + ", &" + counter.FullName + ", " + codeBuffer.OSRCount + ", " + input + ")";
                    codeBuffer.OSRCount++;
                }
                else if (component is CTU)
                {
                    buffer = CTU_FN + "(" + counter.Limit + ", &" + counter.FullName + ", " + codeBuffer.OSRCount + ", " + input + ")";
                    codeBuffer.OSRCount++;
                }
            }

            return(buffer);
        }
Exemple #4
0
        /// <summary>
        /// Compile a single output component
        /// </summary>
        /// <param name="component">Component to be compiled</param>
        /// <param name="codeBuffer">Compiler's code buffer</param>
        /// <returns>If and else statements</returns>
        internal static Tuple <string, string> CompileOutputComponent(ComponentBase component, CompilerBuffer codeBuffer)
        {
            string ifCommand = string.Empty, elseCommand = string.Empty;

            if (component is Coil)
            {
                Coil coil = component as Coil;
                switch (coil.Mode)
                {
                case Coil.CoilMode.Negated:
                    ifCommand   = coil.FullName + " = false;";
                    elseCommand = coil.FullName + " = true;";
                    break;

                case Coil.CoilMode.Normal:
                    ifCommand   = coil.FullName + " = true;";
                    elseCommand = coil.FullName + " = false;";
                    break;

                case Coil.CoilMode.Reset:
                    ifCommand = coil.FullName + " = false;";
                    break;

                case Coil.CoilMode.Set:
                    ifCommand = coil.FullName + " = true;";
                    break;
                }
            }
            else if (component is ADC)
            {
                ifCommand = (component as ADC).Destination + " = analogRead(" + (component as ADC).FullName + ");";
            }
            else if (component is PWM)
            {
                ifCommand   = "analogWrite(" + (component as PWM).FullName + ", " + (component as PWM).DudyCycle + ");";
                elseCommand = "analogWrite(" + (component as PWM).FullName + ", 0);";
            }
            else if (component is RES)
            {
                ifCommand = (component as RES).FullName + " = 0;";
            }
            else if (component is CTC)
            {
                CTC ctc = component as CTC;
                ifCommand   = "if (" + OSR_FN + "(" + codeBuffer.OSRCount + ", true)) " + ctc.FullName + " = (" + ctc.FullName + " >= " + ctc.Limit + ") ? 0 : " + ctc.FullName + " + 1;";
                elseCommand = OSR_FN + "(" + codeBuffer.OSRCount + ", false));";
                codeBuffer.OSRCount++;
            }
            else if (component is MathComponent)
            {
                MathComponent mc = component as MathComponent;

                if (component is ADD)
                {
                    ifCommand = mc.Destination + " = " + mc.VarA + " + " + mc.VarB + ";";
                }
                else if (component is DIV)
                {
                    ifCommand = mc.Destination + " = " + mc.VarA + " / " + mc.VarB + ";";
                }
                else if (component is MUL)
                {
                    ifCommand = mc.Destination + " = " + mc.VarA + " * " + mc.VarB + ";";
                }
                else if (component is SUB)
                {
                    ifCommand = mc.Destination + " = " + mc.VarA + " - " + mc.VarB + ";";
                }
                else if (component is MOV)
                {
                    ifCommand = mc.Destination + " = " + mc.VarA + ";";
                }
            }
            else if (component is ELF)
            {
                ifCommand = (component as ELF).Name + "();";
            }

            return(new Tuple <string, string>(ifCommand, elseCommand));
        }
        /// <summary>
        /// Generate code from data table variables
        /// </summary>
        /// <param name="table"></param>
        /// <param name="codeBuffer"></param>
        internal static void CompileDataTable(LadderDataTable table, CompilerBuffer codeBuffer)
        {
            List <Tuple <string, Type, LDVarClass, object> > tuples = table.ListAllData().OrderBy(x => x.Item1).ToList();

            codeBuffer.Globals.Add("//Inputs");
            StringBuilder inputList = new StringBuilder();

            foreach (var tuple in tuples.Where(x => x.Item3 == LDVarClass.Input))
            {
                codeBuffer.Globals.Add("boolean " + tuple.Item1 + ";");
            }

            codeBuffer.Globals.Add(string.Empty);
            codeBuffer.Globals.Add("//Outputs");
            foreach (var tuple in tuples.Where(x => x.Item3 == LDVarClass.Output))
            {
                codeBuffer.Globals.Add("boolean " + tuple.Item1 + ";");
            }

            codeBuffer.Globals.Add(string.Empty);
            codeBuffer.Globals.Add("//Data");
            foreach (var tuple in tuples.Where(x => x.Item3 == LDVarClass.Data))
            {
                switch (tuple.Item2.ToString().Replace("System.", string.Empty))
                {
                case "Boolean":
                    codeBuffer.Globals.Add("boolean " + tuple.Item1 + " = " + (((bool)tuple.Item4) ? "true;" : "false;"));
                    break;

                case "Int16":
                    codeBuffer.Globals.Add("int " + tuple.Item1 + " = " + tuple.Item4.ToString() + ";");
                    break;

                case "Byte":
                    codeBuffer.Globals.Add("byte " + tuple.Item1 + " = " + tuple.Item4.ToString() + ";");
                    break;

                default:
                    throw new FormatException("Unrecognized variable type in data table");
                }
            }


            foreach (var tuple in tuples.Where(x => x.Item3 == LDVarClass.InFunction))
            {
                List <string> buffer = new List <string>();
                buffer.Add("boolean " + tuple.Item1 + "(boolean input)");
                buffer.Add("{");
                foreach (string line in tuple.Item4.ToString().Split('\n'))
                {
                    buffer.Add(INDENT + line);
                }
                buffer.Add("}");
                codeBuffer.Functions.Add(buffer);
            }

            foreach (var tuple in tuples.Where(x => x.Item3 == LDVarClass.OutFunction))
            {
                List <string> buffer = new List <string>();
                buffer.Add("void " + tuple.Item1 + "()");
                buffer.Add("{");
                foreach (string line in tuple.Item4.ToString().Split('\n'))
                {
                    buffer.Add(INDENT + line);
                }
                buffer.Add("}");
                codeBuffer.Functions.Add(buffer);
            }
        }
Exemple #6
0
        /// <summary>
        /// Compile the diagram's rung collection
        /// </summary>
        /// <param name="rungs"></param>
        /// <param name="codeBuffer"></param>
        internal static void CompileRungs(IEnumerable <Rung> rungs, CompilerBuffer codeBuffer)
        {
            foreach (Rung rung in rungs)
            {
                #region Buffers
                List <string>         tempStatements = new List <string>();
                List <NodeExpression> nodes          = new List <NodeExpression>().RunAnalysis(rung);
                List <NodeOutputs>    outputs        = new List <NodeOutputs>();
                #endregion

                #region Analysis Loop
                foreach (ComponentBase component in rung.Components)
                {
                    NodeExpression NodeA = nodes.GetNodeConnections(component.LeftLide);
                    NodeExpression NodeB = nodes.GetNodeConnections(component.RightLide);

                    if (component.GetCompilerClass() == ComponentCompilerClass.Input)
                    {
                        if (!string.IsNullOrEmpty(NodeA.Expression))
                        {
                            NodeB += string.Format(NODE_NUMBER_MARKER + "{0} && {1}", nodes.IndexOf(NodeA), CompileInputComponent(component));
                        }
                        else
                        {
                            NodeB += CompileInputComponent(component);
                        }
                    }
                    else
                    {
                        NodeExpression lastParallel = nodes.GetLastParallel(NodeA);

                        if (!string.IsNullOrEmpty(NodeA.Expression) && !lastParallel.IsTempValue)
                        {
                            tempStatements.Add(string.Format(RATD + "[{0}]" + " = {1};", tempStatements.Count, lastParallel.Expression));
                            lastParallel.Expression  = string.Format(RATD + "[{0}]", tempStatements.Count - 1);
                            lastParallel.IsTempValue = true;
                        }

                        if (component.GetCompilerClass() == ComponentCompilerClass.InputFunction)
                        {
                            if (!string.IsNullOrEmpty(NodeA.Expression))
                            {
                                NodeB += CompileInputFunctionComponent(component, NODE_NUMBER_MARKER + nodes.IndexOf(NodeA), codeBuffer);
                            }
                            else
                            {
                                NodeB += CompileInputFunctionComponent(component, TRUE, codeBuffer);
                            }
                        }
                        else
                        {
                            outputs.AddOutputs(NodeA.Node, CompileOutputComponent(component, codeBuffer));
                        }
                    }
                }
                #endregion

                if (codeBuffer.BoolTempCount < tempStatements.Count)
                {
                    codeBuffer.BoolTempCount = tempStatements.Count;
                }

                List <string> sRung = BuildRung(tempStatements, nodes, outputs);
                if (!string.IsNullOrEmpty(rung.Comment))
                {
                    sRung.Insert(0, "/*" + rung.Comment + "*/");
                }

                codeBuffer.Rungs.Add(sRung);
            }
        }
Exemple #7
0
        /// <summary>
        /// Generate the automatic ladder functions
        /// </summary>
        /// <param name="codeBuffer"></param>
        /// <param name="codeBuilder"></param>
        private static void LadderFunctionBuilder(CompilerBuffer codeBuffer, StringBuilder codeBuilder)
        {
            #region OSF
            if (codeBuffer.OSFCount > 0)
            {
                codeBuilder.AppendLine("boolean " + OSF_FN + "(int n, boolean input){");
                codeBuilder.AppendLine(INDENT + "byte *osf = &" + OSF_DATA + "[n / 8];");
                codeBuilder.AppendLine(INDENT + "int j = (n % 8);");
                codeBuilder.AppendLine(INDENT + "boolean prev = bitRead(*osf, j);");
                codeBuilder.AppendLine(INDENT + "bitWrite(*osf, j, input);");
                codeBuilder.AppendLine(INDENT + "return prev && !input;");
                codeBuilder.AppendLine("}");
                codeBuilder.AppendLine();
            }
            #endregion

            #region OSR
            if (codeBuffer.OSRCount + codeBuffer.CTDCount + codeBuffer.CTUCount > 0)
            {
                codeBuilder.AppendLine("boolean " + OSR_FN + "(int n, boolean input){");
                codeBuilder.AppendLine(INDENT + "byte *osr = &" + OSR_DATA + "[n / 8];");
                codeBuilder.AppendLine(INDENT + "int j = (n % 8);");
                codeBuilder.AppendLine(INDENT + "boolean prev = bitRead(*osr, j);");
                codeBuilder.AppendLine(INDENT + "bitWrite(*osr, j, input);");
                codeBuilder.AppendLine(INDENT + "return !prev && input;");
                codeBuilder.AppendLine("}");
                codeBuilder.AppendLine();
            }
            #endregion

            #region CTD
            if (codeBuffer.CTDCount > 0)
            {
                codeBuilder.AppendLine("boolean " + CTD_FN + "(int limit, int *dest, int osr, boolean input){");
                codeBuilder.AppendLine(INDENT + "if (" + OSR_FN + "(osr, input)) *dest -= 1;");
                codeBuilder.AppendLine(INDENT + "return *dest >= limit;");
                codeBuilder.AppendLine("}");
                codeBuilder.AppendLine();
            }
            #endregion

            #region CTU
            if (codeBuffer.CTUCount > 0)
            {
                codeBuilder.AppendLine("boolean " + CTU_FN + "(int limit, int *dest, int osr, boolean input){");
                codeBuilder.AppendLine(INDENT + "if (" + OSR_FN + "(osr, input)) *dest += 1;");
                codeBuilder.AppendLine(INDENT + "return *dest >= limit;");
                codeBuilder.AppendLine("}");
                codeBuilder.AppendLine();
            }
            #endregion

            #region Refresh Inputs
            if (codeBuffer.InputRefreshContent.Count > 0)
            {
                codeBuilder.AppendLine("void " + REFRESH_INPUT_FN + "(){");
                foreach (string item in codeBuffer.InputRefreshContent)
                {
                    codeBuilder.AppendLine(INDENT + item);
                }
                codeBuilder.AppendLine("}");
                codeBuilder.AppendLine();
            }
            #endregion

            #region Refresh Outputs
            if (codeBuffer.OutputRefreshContent.Count > 0)
            {
                codeBuilder.AppendLine("void " + REFRESH_OUTPUT_FN + "(){");
                foreach (string item in codeBuffer.OutputRefreshContent)
                {
                    codeBuilder.AppendLine(INDENT + item);
                }
                codeBuilder.AppendLine("}");
                codeBuilder.AppendLine();
            }
            #endregion
        }
Exemple #8
0
        /// <summary>
        /// Assemble the code parts into a finished compiled code
        /// </summary>
        /// <param name="codeBuffer"></param>
        /// <returns></returns>
        internal static string CodeBuilder(CompilerBuffer codeBuffer)
        {
            StringBuilder codeBuilder = new StringBuilder();

            codeBuilder.AppendLine("// Code generated by Ladderino V " + COMPILER_VERSION);
            codeBuilder.AppendLine("// Developed by: Allan Leon");
            codeBuilder.AppendLine();

            #region Defines
            if (codeBuffer.Defines.Count > 0)
            {
                codeBuilder.AppendLine("/* ================================[ Defines ]=============================== */");
                foreach (string item in codeBuffer.Defines)
                {
                    codeBuilder.AppendLine(item);
                }
                codeBuilder.AppendLine("/* ========================================================================== */");
                codeBuilder.AppendLine();
            }
            #endregion Defines

            #region Includes
            if (codeBuffer.Includes.Count > 0)
            {
                codeBuilder.AppendLine("/* ===============================[ Includes ]=============================== */");
                foreach (string item in codeBuffer.Includes)
                {
                    codeBuilder.AppendLine(item);
                }
                codeBuilder.AppendLine("/* ========================================================================== */");
                codeBuilder.AppendLine();
            }
            #endregion Includes

            #region Global Variables
            codeBuilder.AppendLine("/* ================================[ Globals ]=============================== */");
            foreach (string item in codeBuffer.Globals)
            {
                codeBuilder.AppendLine(item);
            }
            if (codeBuffer.OSFCount > 0)
            {
                codeBuilder.AppendLine("byte " + OSF_DATA + "[" + ((int)(codeBuffer.OSFCount / 8) + 1) + "];");
            }
            if (codeBuffer.OSRCount > 0)
            {
                codeBuilder.AppendLine("byte " + OSR_DATA + "[" + ((int)(codeBuffer.OSRCount / 8) + 1) + "];");
            }
            codeBuilder.AppendLine("/* ========================================================================== */");
            codeBuilder.AppendLine();
            #endregion Global Variables

            #region Ladder Functions
            codeBuilder.AppendLine("/* ===========================[ Ladder Functions ]=========================== */");
            LadderFunctionBuilder(codeBuffer, codeBuilder);
            codeBuilder.AppendLine("/* ========================================================================== */");
            codeBuilder.AppendLine();
            #endregion Ladder Functions

            #region User Functions
            if (codeBuffer.Functions.Count > 0)
            {
                codeBuilder.AppendLine("/* ===============================[ Functions ]============================== */");
                foreach (var item in codeBuffer.Functions)
                {
                    foreach (string line in item)
                    {
                        codeBuilder.AppendLine(line);
                    }
                    codeBuilder.AppendLine();
                }
                codeBuilder.AppendLine("/* ========================================================================== */");
                codeBuilder.AppendLine();
            }
            #endregion User Functions

            #region Main
            codeBuilder.AppendLine("/* =================================[ Main ]================================= */");

            #region Setup
            codeBuilder.AppendLine("void setup() {");
            foreach (string item in codeBuffer.SetupContent)
            {
                codeBuilder.AppendLine(INDENT + item);
            }
            codeBuilder.AppendLine("}");
            codeBuilder.AppendLine();
            #endregion

            #region Loop
            codeBuilder.AppendLine("void loop() {");
            if (codeBuffer.BoolTempCount > 0)
            {
                codeBuilder.AppendLine(INDENT + "boolean " + RATD + "[" + codeBuffer.BoolTempCount + "]; //Rung Activation Temporary Data");
            }
            if (codeBuffer.InputRefreshContent.Count > 0)
            {
                codeBuilder.AppendLine(INDENT + REFRESH_INPUT_FN + "();");
            }
            codeBuilder.AppendLine();

            for (int c = 0; c < codeBuffer.Rungs.Count; c++)
            {
                codeBuilder.AppendLine(INDENT + "//Rung " + c + " Code:");
                foreach (string item in codeBuffer.Rungs[c])
                {
                    codeBuilder.AppendLine(INDENT + item);
                }
                codeBuilder.AppendLine();
            }

            if (codeBuffer.OutputRefreshContent.Count > 0)
            {
                codeBuilder.AppendLine(INDENT + REFRESH_OUTPUT_FN + "();");
            }

            codeBuilder.AppendLine("}");
            codeBuilder.AppendLine();
            #endregion

            codeBuilder.AppendLine("/* ========================================================================== */");
            codeBuilder.AppendLine();
            #endregion Main

            return(codeBuilder.ToString());
        }