MotionLib  1.0.0
SamBuCa motion library
MFEAxisPositionMonitor.cpp
1 /*
2 ** Copyright (C) 2025 CERN
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: 2025-04-17T18:13:59
21 ** Author: Sylvain Fargier <sylvain.fargier@cern.ch>
22 */
23 
24 #include "MFEAxisPositionMonitor.hpp"
25 
26 #include <ccut/async.hpp>
27 #include <ccut/utils.hpp>
28 
29 #include "MFEPlatform.hpp"
30 #include "device/AxisPositionMonitor.hpp"
31 #include "platform/specialized/MFEPlatform/MFEAxis.hpp"
32 
33 using namespace smc;
34 using namespace smc::internal;
37 
38 MFEAxisPositionMonitor::MFEAxisPositionMonitor(
39  const std::string &uid,
40  const std::shared_ptr<Axis> &axis,
41  const std::shared_ptr<PositionSensor> &position,
42  const std::shared_ptr<MFEPlatform> &mfe) :
43  AxisPositionMonitor{uid, axis, position},
44  m_mfe{mfe}
45 {}
46 
47 static inline std::future<units::value_t> getReg(MFEPlatform::Shared &mfe,
48  const std::string &regName)
49 {
50  return mfe->run<units::value_t>(
51  [regName](ImmediateCmd &cmd, const MGrblPlatform::Context &mgrblCtx) {
52  const MFEPlatform::Context &ctx(
53  static_cast<const MFEPlatform::Context &>(mgrblCtx));
54 
55  RegInfo info;
56  if (!ctx.edge)
57  throw Exception{ErrorCode::InvalidArguments,
58  "edge driver not available"};
59  else if (!ctx.getRegInfo(regName, info))
60  throw Exception{ErrorCode::InvalidArguments,
61  "failed to get reg info: " + regName};
62 
63  uint32_t value;
64  ctx.edge->read(info.reg, info.shift, value);
65  units::value_t ret{
66  units::steps,
67  units::value_t::value_type(reinterpret_cast<int32_t &>(value))};
68  cmd.prom->get<units::value_t>().set_value(ret);
69  });
70 }
71 
72 std::future<units::value_t> MFEAxisPositionMonitor::getDifference(
73  units::unit_t unit) const
74 {
75  try
76  {
77  if (unit != units::steps)
78  throw Exception{ErrorCode::IncompatibleUnits,
79  "failed to convert to " + to_string(unit)};
80 
81  MFEPlatform::Shared mfe(m_mfe.lock());
82  if (!mfe)
83  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
84 
85  const std::string regName{uid() + "/diff"};
86  return getReg(mfe, regName);
87  }
88  catch (const Exception &ex)
89  {
90  return ccut::make_future_error<units::value_t>(ex);
91  }
92 }
93 
94 std::future<units::value_t> MFEAxisPositionMonitor::getMaxDifference(
95  units::unit_t unit) const
96 {
97  try
98  {
99  if (unit != units::steps)
100  throw Exception{ErrorCode::IncompatibleUnits,
101  "failed to convert to " + to_string(unit)};
102 
103  MFEPlatform::Shared mfe(m_mfe.lock());
104  if (!mfe)
105  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
106 
107  const std::string regName{uid() + "/diff/max"};
108  return getReg(mfe, regName);
109  }
110  catch (const Exception &ex)
111  {
112  return ccut::make_future_error<units::value_t>(ex);
113  }
114 }
115 
116 std::future<AxisPositionMonitor::State> MFEAxisPositionMonitor::getState() const
117 {
118  try
119  {
120  MFEPlatform::Shared mfe(m_mfe.lock());
121  std::shared_ptr<const MFEAxisPositionMonitor> self{
122  std::static_pointer_cast<const MFEAxisPositionMonitor>(
123  shared_from_this())};
124 
125  if (!mfe)
126  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
127 
128  return mfe->run<State>(
129  [self, mfe](ImmediateCmd &cmd, MGrblPlatform::Context &ctx) {
130  mfe->processUpdate(ctx);
131 
132  cmd.prom->get<State>().set_value(self->lastState());
133  });
134  }
135  catch (const Exception &ex)
136  {
137  return ccut::make_future_error<State>(ex);
138  }
139 }
140 
141 std::future<void> MFEAxisPositionMonitor::setEnabled(bool enabled)
142 {
143  try
144  {
145  MFEPlatform::Shared mfe(m_mfe.lock());
146  if (!mfe)
147  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
148 
149  const std::string regName{uid() + "/slost/gcr"};
150  return mfe->run<void>(
151  [regName, enabled](ImmediateCmd &cmd,
152  const MGrblPlatform::Context &mgrblCtx) {
153  const MFEPlatform::Context &ctx(
154  static_cast<const MFEPlatform::Context &>(mgrblCtx));
155 
156  RegInfo info;
157  if (!ctx.edge)
158  throw Exception{ErrorCode::InvalidArguments,
159  "edge driver not available"};
160  else if (!ctx.getRegInfo(regName, info))
161  throw Exception{ErrorCode::InvalidArguments,
162  "failed to get reg info: " + regName};
163  uint32_t gcr;
164  uint32_t mask{info.mask << info.shift};
165  ctx.edge->read(info.reg, gcr);
166 
167  // if already enabled, disable it to reset internal state
168  if (!enabled || !(gcr & mask))
169  ctx.edge->write(info.reg, gcr | mask);
170  if (enabled)
171  ctx.edge->write(info.reg, gcr & ~mask);
172 
173  logger::info(MFEPlatform::s_loggerCat)
174  << "step-lost detection "
175  << (enabled ? "enabled" : "disabled") << " on " << regName;
176  cmd.prom->get<void>().set_value();
177  });
178  }
179  catch (const Exception &ex)
180  {
181  return ccut::make_future_error<void>(ex);
182  }
183 }
184 
186 {
187  MFEPlatform::Shared mfe(m_mfe.lock());
188  if (!mfe)
189  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
190  else if (unit != units::steps)
191  throw Exception(ErrorCode::IncompatibleUnits,
192  "failed to convert position");
193 
194  const std::string &uid{this->uid()};
195  uint32_t diff;
196  mfe->getResolverMonitorState(
197  uid.substr(
198  0, uid.length() - MFEPlatform::s_resolverMonitorSuffix.length()),
199  diff);
200  return units::value_t{units::steps,
201  double(*reinterpret_cast<const int32_t *>(&diff))};
202 }
203 
204 AxisPositionMonitor::State MFEAxisPositionMonitor::lastState() const
205 {
206  MFEPlatform::Shared mfe(m_mfe.lock());
207  if (!mfe)
208  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
209 
210  const std::string &uid{this->uid()};
211  uint32_t diff;
212  return mfe->getResolverMonitorState(
213  uid.substr(
214  0, uid.length() - MFEPlatform::s_resolverMonitorSuffix.length()),
215  diff);
216 }
217 
218 std::future<std::set<std::string>> MFEAxisPositionMonitor::listConfig() const
219 {
220  try
221  {
222  std::shared_ptr<MFEPlatform> mfe(m_mfe.lock());
223  if (!mfe)
224  throw Exception(ErrorCode::Canceled, "platform stopped (deleted)");
225 
226  grbl::Axis grblAxis = mfe->getResolverMonitorAxis(uid());
227 
228  return mfe->run<std::set<std::string>>(
229  [grblAxis, mfe](ImmediateCmd &cmd, MGrblPlatform::Context &ctx) {
230  std::set<std::string> ret;
231  mfe->runOnInstance(
232  ctx,
233  [&ret, grblAxis](GrblPlatform::Shared &,
234  GrblPlatform::Context &ctx) {
235  for (const std::string &name : ctx.listConfig(grblAxis))
236  {
237  if (ccut::startsWith(
238  name, MFEPlatform::s_resolverSettingPrefix))
239  {
240  const std::string setting{name.substr(
241  MFEPlatform::s_resolverSettingPrefix.size())};
242  if (!MFEPlatform::s_monitorConfigHidden.count(
243  setting))
244  ret.insert(setting);
245  }
246  }
247  });
248 
249  cmd.prom->get<std::set<std::string>>().set_value(ret);
250  });
251  }
252  catch (const Exception &ex)
253  {
254  return ccut::make_future_error<std::set<std::string>>(ex);
255  }
256 }
257 
258 std::future<std::string> MFEAxisPositionMonitor::getConfig(
259  const std::string &name) const
260 {
261  try
262  {
263  PositionSensor::Shared position{positionSensorDevice()};
264 
265  if (!position)
266  throw Exception(
267  ErrorCode::InvalidArguments,
268  "Failed to find positionSensor for device: " + uid());
269 
270  return position->getConfig(name);
271  }
272  catch (const Exception &ex)
273  {
274  return ccut::make_future_error<std::string>(ex);
275  }
276 }
277 
278 std::future<void> MFEAxisPositionMonitor::setConfig(const std::string &name,
279  const std::string &value) const
280 {
281  try
282  {
283  PositionSensor::Shared position{positionSensorDevice()};
284 
285  if (!position)
286  throw Exception(
287  ErrorCode::InvalidArguments,
288  "Failed to find positionSensor for device: " + uid());
289 
290  return position->setConfig(name, value);
291  }
292  catch (const Exception &ex)
293  {
294  return ccut::make_future_error(ex);
295  }
296 }
This object represent a link between an axis and a position sensor.
DeviceId uid() const
Get the address of device.
Definition: DeviceBase.cpp:76
Exception thrown by MotionController in case of issues with command.
Definition: Exception.hpp:61
units::value_t lastDifference(units::unit_t unit) const override
Get last known difference.
std::future< void > setEnabled(bool enabled) override
Enable/disable the monitor.
std::future< State > getState() const override
Get the current device state.
std::future< std::set< std::string > > listConfig() const override
list device configuration options
std::future< void > setConfig(const std::string &name, const std::string &value) const override
set device configuration value
std::future< units::value_t > getMaxDifference(units::unit_t unit) const override
Get max difference since monitor was enabled.
std::future< std::string > getConfig(const std::string &name) const override
get device configuration value
State lastState() const override
Get last known state.
const std::string & to_string(Axis::State state)
convert State to string
Definition: Axis.cpp:78
main motion-lib namespace
Definition: Client.cpp:30
std::set< std::string > listConfig()
list config values
bool getRegInfo(const std::string &uid, RegInfo &info) const
Get the RegInfo object.