#pragma once #include "project_limits.h" #include "register_address.h" #include #include #include #include #include enum class ContactMode { NormallyOpen, NormallyClosed }; enum class CoilMode { Normal, Set, Reset }; enum class EdgeMode { Rising, Falling }; enum class ComparisonOperator { Equal, NotEqual, LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual }; enum class WordOperandKind { Constant, Register }; struct WordOperand { WordOperandKind kind = WordOperandKind::Constant; RegisterAddress address{RegisterArea::D, 0}; std::int16_t constant = 0; bool validate(std::string *error = nullptr) const; }; struct ContactNodeConfig { RegisterAddress address{RegisterArea::M, 0}; ContactMode mode = ContactMode::NormallyOpen; }; struct EdgeContactNodeConfig { RegisterAddress address{RegisterArea::M, 0}; EdgeMode mode = EdgeMode::Rising; }; struct CoilNodeConfig { RegisterAddress address{RegisterArea::M, 0}; CoilMode mode = CoilMode::Normal; }; struct CompareNodeConfig { RegisterAddress address{RegisterArea::D, 0}; ComparisonOperator comparison = ComparisonOperator::Equal; std::int16_t value = 0; }; struct MoveNodeConfig { WordOperand source; RegisterAddress destination{RegisterArea::D, 0}; }; enum class ArithmeticOperation { Add, Subtract }; struct ArithmeticNodeConfig { ArithmeticOperation operation = ArithmeticOperation::Add; WordOperand left; WordOperand right; RegisterAddress destination{RegisterArea::D, 0}; }; using LogicNodeConfig = std::variant< ContactNodeConfig, EdgeContactNodeConfig, CoilNodeConfig, CompareNodeConfig, MoveNodeConfig, ArithmeticNodeConfig>; std::optional registerAddressForLogicNode( const LogicNodeConfig &config); void collectRegisterAddressesForLogicNode( const LogicNodeConfig &config, std::vector *addresses); struct LogicNode { std::string id; LogicNodeConfig config; bool configured = true; bool validate(std::string *error = nullptr) const; bool isConfigured() const; bool isCondition() const; bool isOutput() const; }; enum class LadderCellKind { Gap, Wire, Node }; // 条件区的一个固定网格,横线和空白与条件节点具有同等持久化地位 struct LadderCell { std::string id; LadderCellKind kind = LadderCellKind::Gap; std::optional node; bool validate(std::string *error = nullptr) const; }; // 两个相邻视觉行之间、指定列边界上的一段竖线 struct VerticalConnection { std::string id; std::string upperRungId; std::string lowerRungId; int columnBoundary = 0; bool validate(std::string *error = nullptr) const; }; // 连续梯形图的一条视觉行,不再是隔离的网络容器 struct LadderRung { std::string id; std::string name; std::string comment; std::optional output; std::vector cells; bool validate(std::string *error = nullptr) const; bool validateStructure(std::string *error = nullptr) const; bool validateForRunning(std::string *error = nullptr) const; }; // 一张连续梯形图,网络由横竖连接关系自然形成 struct ControlLogic { std::string id; std::string name; std::vector rungs; bool enabled = true; std::vector verticalConnections; std::size_t networkHeadIndex(std::size_t rung_index) const; bool validate( const ProjectLimitSettings &limits, std::string *error = nullptr) const; bool validateStructure(std::string *error = nullptr) const; bool validateStructure( const ProjectLimitSettings &limits, std::string *error = nullptr) const; bool validateForRunning(std::string *error = nullptr) const; bool validateForRunning( const ProjectLimitSettings &limits, std::string *error = nullptr) const; }; const LadderCell *findLadderCell( const LadderRung &rung, const std::string &cell_id); LadderCell *findLadderCell( LadderRung &rung, const std::string &cell_id); const VerticalConnection *findVerticalConnection( const ControlLogic &logic, const std::string &connection_id); VerticalConnection *findVerticalConnection( ControlLogic &logic, const std::string &connection_id); void collectConditionNodes( const LadderRung &rung, std::vector *nodes); void collectLogicNodes( const ControlLogic &logic, std::vector *nodes);