MotionLib  1.0.0
SamBuCa motion library
GrblGenerator.cpp
1 /*
2 ** Copyright (C) 2020 Sylvain Fargier
3 **
4 ** This software is provided 'as-is', without any express or implied
5 ** warranty. In no event will the authors be held liable for any damages
6 ** arising from the use of this software.
7 **
8 ** Permission is granted to anyone to use this software for any purpose,
9 ** including commercial applications, and to alter it and redistribute it
10 ** freely, subject to the following restrictions:
11 **
12 ** 1. The origin of this software must not be misrepresented; you must not
13 ** claim that you wrote the original software. If you use this software
14 ** in a product, an acknowledgment in the product documentation would be
15 ** appreciated but is not required.
16 ** 2. Altered source versions must be plainly marked as such, and must not be
17 ** misrepresented as being the original software.
18 ** 3. This notice may not be removed or altered from any source distribution.
19 **
20 ** Created on: 2022-02-16T11:51:45+01:00
21 ** Author: Sylvain Fargier <fargie_s> <sylvain.fargier@cern.ch>
22 **
23 */
24 
25 #include "GrblGenerator.hpp"
26 
27 #include <cmath>
28 #include <iomanip>
29 #include <ios>
30 #include <iostream>
31 #include <sstream>
32 
33 #include <logger/Logger.hpp>
34 
35 using namespace logger;
36 
37 static const std::string s_loggerCat{"grbl:gen"};
38 
39 namespace grbl {
40 
41 namespace gen {
42 
43 const Modal DistanceMode::Relative{DistanceMode::modalGroup, "G91"};
44 const Modal DistanceMode::Absolute{DistanceMode::modalGroup, "G90"};
45 
46 const Modal MotionMode::Rapid{MotionMode::modalGroup, "G0"};
47 const Modal MotionMode::Linear{MotionMode::modalGroup, "G1"};
48 
49 const Modal NonModal::Dwell{NonModal::modalGroup, "G4"};
50 const Modal NonModal::AbsoluteOverride{NonModal::modalGroup, "G53"};
51 const Modal NonModal::SetCoordinateOffset{NonModal::modalGroup, "G92"};
52 const Modal NonModal::ResetCoordinateOffset{NonModal::modalGroup, "G92.1"};
53 const Modal NonModal::ClearCoordinateOffset{NonModal::modalGroup, "G92.2"};
54 const Modal NonModal::RestoreCoordinateOffset{NonModal::modalGroup, "G92.3"};
55 
56 Modal DigitalOut::on(uint8_t port, bool immediate)
57 {
58  std::string val = "M" + std::string(immediate ? "64" : "62");
59  val += "P" + std::to_string(port);
60  return Modal{DigitalOut::modalGroup, val};
61 }
62 
63 Modal DigitalOut::off(uint8_t port, bool immediate)
64 {
65  std::string val = "M" + std::string(immediate ? "65" : "63");
66  val += "P" + std::to_string(port);
67  return Modal{DigitalOut::modalGroup, val};
68 }
69 
70 Modal CoordinateSystem::set(uint8_t system)
71 {
72  char out[]{'G', '5', '4', 0};
73  if (system >= 54)
74  out[2] += (system - 54);
75  else
76  out[2] += (system);
77  return Modal{CoordinateSystem::modalGroup, out};
78 }
79 
80 Modal NonModal::SetCoordinate(int8_t system, bool relative)
81 {
82  char parg[]{'P', '0', 0};
83  if (system >= 54)
84  parg[1] += system - 54 + 1;
85  else if (system >= 0)
86  parg[1] += system + 1;
87 
88  const char *larg = relative ? "L20" : "L2";
89 
90  return Modal{NonModal::modalGroup, (std::string("G10") + larg) + parg};
91 }
92 
93 Modal NonModal::GoHome(uint8_t index)
94 {
95  return Modal{NonModal::modalGroup, (index == 0) ? "G28" : "G30"};
96 }
97 
98 Modal NonModal::SetHome(uint8_t index)
99 {
100  return Modal{NonModal::modalGroup, (index == 0) ? "G28.1" : "G30.1"};
101 }
102 
103 const std::string Realtime::Reset = "\x18";
104 const std::string Realtime::CycleStart = "\x81";
105 const std::string Realtime::FeedHold = "\x82";
106 const std::string Realtime::StatusReport = "?";
107 const std::string System::ParserState = "$G"; // $G
108 const std::string System::Jog = "$J"; // $J
109 const std::string System::NGCParams = "$#"; // $#
110 const std::string System::Settings = "$$"; // $$
111 const std::string System::AllSettings = "$+"; // $+
112 const std::string System::ToggleBlockDelete = "$B"; // $B
113 const std::string System::ToggleSingleBlock = "$S"; // $S
114 const std::string System::ToggleOptionalStop = "$O"; // $O
115 const std::string System::CheckMode = "$C"; // $C
116 const std::string System::DisableLock = "$X"; // $X
117 const std::string System::Home = "$H"; // $H $HX $HY $HZ $HA $HB $HC
118 const std::string System::Help = "$HELP"; // $HELP
119 const std::string System::Sleep = "$SLP"; // $SLP
120 const std::string System::SetToolReference = "$TLR"; // $TLR
121 const std::string System::ToolProbeWorkpiece = "$TLR"; // $TLR
122 const std::string System::BuildInfo = "$I"; // $I
123 const std::string System::AllBuildInfo = "$I+"; // $I+
124 const std::string System::SettingsReset = "$RST"; // $RST
125 const std::string System::StartupLines = "$N"; // $N $N0 $N1
126 const std::string System::EnumerateAlarms = "$EA"; // $EA
127 const std::string System::EnumerateErrors = "$EE"; // $EE
128 const std::string System::EnumerateGroups = "$EG"; // $EG
129 const std::string System::EnumerateSettings = "$ES"; // $ES
130 const std::string System::EnumerateAll = "$E*"; // $E*
131 const std::string System::EnumeratePins = "$PINS"; // $PINS
132 const std::string System::ReportLastSignalsEvent = "$LEV"; // $LEV
133 const std::string System::ReportCurrentLimitState = "$LIM"; // $LIM
134 const std::string System::ReportSpindleData = "$SD"; // $SD
135 const std::string System::SpindleResetData = "$SR"; // $SR
136 
137 const Logger &operator<<(const Logger &logger, const Modal &modal)
138 {
139  if (logger.isEnabled())
140  {
141  logger << "Modal(" << modal.group << ", " << modal.value << ")";
142  }
143  return logger;
144 }
145 const Logger &operator<<(const Logger &logger, const Position &pos)
146 {
147  if (logger.isEnabled())
148  {
149  logger << "Position(" << pos.axis << std::fixed << std::setprecision(3)
150  << pos.value << logger::clearflags << ")";
151  }
152  return logger;
153 }
154 std::string to_string(ModalGroup group)
155 {
156  switch (group)
157  {
158  case ModalGroup::NonModal: return "NonModal";
159  case ModalGroup::MotionMode: return "MotionMode";
160  case ModalGroup::PlaneSelect: return "PlaneSelect";
161  case ModalGroup::DistanceMode: return "DistanceMode";
162  case ModalGroup::ArcIJKDistanceMode: return "ArcIJKDistanceMode";
163  case ModalGroup::FeedRateMode: return "FeedRateMode";
164  case ModalGroup::Units: return "Units";
165  case ModalGroup::CutterRadiusCompensation:
166  return "CutterRadiusCompensation";
167  case ModalGroup::ToolLengthOffset: return "ToolLengthOffset";
168  case ModalGroup::CCRetractMode: return "CCRetractMode";
169  case ModalGroup::Scaling: return "Scaling";
170  case ModalGroup::CoordinateSystem: return "CoordinateSystem";
171  case ModalGroup::ControlMode: return "ControlMode";
172  case ModalGroup::SpindleSpeedMode: return "SpindleSpeedMode";
173  case ModalGroup::LatheDiameterMode: return "LatheDiameterMode";
174 
175  case ModalGroup::ProgramFlow: return "ProgramFlow";
176  case ModalGroup::ToolChange: return "ToolChange";
177  case ModalGroup::SpindleTurning: return "SpindleTurning";
178  case ModalGroup::CoolantControl: return "CoolantControl";
179  case ModalGroup::Override: return "Override";
180  case ModalGroup::DigitalOut: return "DigitalOut";
181  default: return "Unknown";
182  }
183 }
184 
185 std::string System::setSetting(SettingId settingId, const std::string &value)
186 {
187  std::ostringstream ss;
188  ss << "$" << settingId << "=" << value;
189  return ss.str();
190 }
191 
192 } // namespace gen
193 
195 {
196  typedef std::map<grbl::Axis, grbl_float_t> PositionsMap;
197  typedef std::map<gen::ModalGroup, std::string> ModalsMap;
198 
199  PositionsMap positions;
200  ModalsMap modals;
201  std::string errorString;
202 };
203 
204 Generator::Generator() : m_data(new GeneratorData) {}
205 
206 std::string Generator::str() const
207 {
208  if (!m_data->errorString.empty())
209  return std::string();
210 
211  std::ostringstream oss;
212  for (const GeneratorData::ModalsMap::value_type &it : m_data->modals)
213  oss << it.second;
214 
215  oss << std::fixed << std::setprecision(3);
216 
217  for (const GeneratorData::PositionsMap::value_type &it : m_data->positions)
218  oss << to_string(it.first) << it.second;
219 
220  return oss.str();
221 }
222 
223 bool Generator::fail() const
224 {
225  return !m_data->errorString.empty();
226 }
227 
228 const std::string &Generator::errorString() const
229 {
230  return m_data->errorString;
231 }
232 
233 const Generator &Generator::operator<<(const gen::Modal &modal) const
234 {
235  if (!fail())
236  {
237  // debug(s_loggerCat) << " << " << modal;
238  GeneratorData &data = *m_data;
239  GeneratorData::ModalsMap::const_iterator it = data.modals.find(
240  modal.group);
241  if (it == data.modals.cend())
242  data.modals[modal.group] = modal.value;
243  else if (it->second != modal.value)
244  {
245  data.errorString = "modal command conflict: " + it->second +
246  " and " + modal.value;
247  error(s_loggerCat) << data.errorString;
248  }
249  }
250  return *this;
251 }
252 
253 const Generator &Generator::operator<<(const gen::Position &pos) const
254 {
255  if (!fail())
256  {
257  // debug(s_loggerCat) << " << " << pos;
258  GeneratorData &data = *m_data;
259  GeneratorData::PositionsMap::iterator it = data.positions.find(pos.axis);
260  if (it == data.positions.cend())
261  data.positions[pos.axis] = pos.value;
262  else if (fabs(it->second - pos.value) >=
263  0.001) // take in account grbl precision
264  {
265  std::ostringstream oss;
266  oss << "position conflict on " << to_string(it->first)
267  << " axis: " << std::fixed << std::setprecision(3) << it->second
268  << " and " << pos.value;
269 
270  data.errorString = oss.str();
271  error(s_loggerCat) << data.errorString;
272  }
273  else
274  {
275  it->second = pos.value;
276  }
277  }
278  return *this;
279 }
280 
281 } // namespace grbl
const std::string & to_string(Axis::State state)
convert State to string
Definition: Axis.cpp:78
ModalGroup
Modal Groups of commands.