24 #include "MFEPlatform.hpp"
29 #include <ccut/async.hpp>
30 #include <fmc_mfe/libfmc_mfe.h>
32 #include "MFEAxis.hpp"
33 #include "MFEAxisPositionMonitor.hpp"
34 #include "MFEEdgeGpio.hpp"
35 #include "MFEPlatformData.hpp"
36 #include "MFEPositionSensor.hpp"
38 #include "device/DeviceBase.hpp"
39 #include "platform/PlatformBase.hpp"
40 #include "platform/specialized/MGrblPlatform/MGrblPlatform.hpp"
41 #include "util/edge/EdgeGrblDeviceBase.hpp"
44 #define MFE_RESOLVER_COUNT 8
46 using namespace logger;
47 using namespace std::chrono;
52 static const std::string s_mfePrefix{
"mfe://"};
53 const std::string MFEPlatform::s_resolverMonitorSuffix{
"/monitor"};
54 const std::string MFEPlatform::s_loggerCat{
"smc:platform:mfe"};
55 const std::string s_modeSettingName{
"mode"};
56 const std::string MFEPlatform::s_resolverSettingPrefix{
"resolver "};
57 const std::string MFEPlatform::s_stepLostConfig{
"step-lost threshold"};
58 const std::set<std::string> MFEPlatform::s_resolverConfigHidden{
59 "step-lost threshold",
"enable",
"position"};
60 const std::set<std::string> MFEPlatform::s_monitorConfigHidden{
61 "position",
"mode",
"enable"};
63 MFEPlatform::MFEPlatform(
const ccut::yml::NodeRef &ref) :
64 MGrblPlatform{ref, new Context(ref)}
66 Context &ctx(
static_cast<Context &
>(*m_ctx));
68 ctx.edge = std::dynamic_pointer_cast<edge::EdgeGrblDeviceBase>(ctx.device);
71 MFEPlatform::~MFEPlatform() {}
73 MGrblAxis::Shared MFEPlatform::createAxis(
74 const std::string &uid,
75 const std::shared_ptr<GrblPlatform> &grbl)
77 return std::make_shared<MFEAxis>(uid, shared_from_this(), grbl);
80 PlatformBase::DeviceTypeList MFEPlatform::getSupportedDevices()
const
82 return DeviceTypeList{DeviceType::AXIS,
86 DeviceType::POSITION_SENSOR,
87 DeviceType::AXIS_POSITION_MONITOR};
90 PlatformBase::DeviceList MFEPlatform::generateDevices(
91 const DeviceTypeList &deviceType)
93 PlatformBase::DeviceList ret{MGrblPlatform::generateDevices(deviceType)};
95 if (deviceType.count(DeviceType::GPIO))
97 std::shared_ptr<MFEPlatform>
self(
98 std::static_pointer_cast<MFEPlatform>(shared_from_this()));
100 std::future<std::list<DeviceBase::Shared>> f =
101 run<std::list<DeviceBase::Shared>>([
self](
ImmediateCmd &cmd,
102 MGrblPlatform::Context &) {
103 Context &ctx(
static_cast<Context &
>(*self->m_ctx));
105 throw Exception(ErrorCode::Runtime,
106 "edge driver not available");
108 std::list<DeviceBase::Shared> ret;
109 self->generateGpios(ctx, ret);
110 cmd.prom->get<std::list<DeviceBase::Shared>>().set_value(ret);
112 if (f.wait_for(milliseconds(3000)) != std::future_status::ready)
114 error(s_loggerCat) <<
"failed to generate Gpios";
118 std::list<DeviceBase::Shared> gpiosList{f.get()};
119 ret.insert(ret.end(), gpiosList.begin(), gpiosList.end());
123 const bool hasAxisPositionMonitor = deviceType.count(
124 DeviceType::AXIS_POSITION_MONITOR);
125 if (deviceType.count(DeviceType::POSITION_SENSOR))
127 std::shared_ptr<MFEPlatform>
self(
128 std::static_pointer_cast<MFEPlatform>(shared_from_this()));
130 const std::string platformUrl = m_ctx->prefix + m_ctx->id;
132 for (
size_t i = 0; i < MFE_RESOLVER_COUNT; ++i)
134 const grbl::Axis grblAxis =
static_cast<grbl::Axis
>(i);
135 MFEPositionSensor::Shared pos = std::make_shared<MFEPositionSensor>(
137 MFEAxisPositionMonitor::Shared mon;
139 if (hasAxisPositionMonitor && deviceType.count(DeviceType::AXIS))
141 const std::string axisUid = platformUrl +
"/axis/" +
143 const auto it = std::find_if(
144 ret.begin(), ret.end(),
145 [&axisUid](
const DeviceBase::Shared &device) {
146 return device->uid() == axisUid &&
147 device->type() == DeviceType::AXIS;
151 mon = std::make_shared<MFEAxisPositionMonitor>(
153 s_resolverMonitorSuffix,
154 std::dynamic_pointer_cast<Axis>(*it), pos,
self);
159 <<
"Failed to find axis for resolver: "
160 << ret.back()->uid() <<
", axis: " << axisUid;
163 const std::string uid{pos->uid()};
164 std::future<void> f = run<void>([
self, grblAxis, i,
166 MGrblPlatform::Context &) {
167 Context &ctx(
static_cast<Context &
>(*self->m_ctx));
169 throw Exception(ErrorCode::Runtime,
170 "edge driver not available");
172 grbl::SettingId modeSettingId = -1;
175 [&modeSettingId, grblAxis](GrblPlatform::Shared &,
176 GrblPlatform::Context &ctx) {
177 modeSettingId = ctx.findSetting(
178 "resolver " + s_modeSettingName,
184 std::lock_guard<std::mutex> guard{
self->m_lock};
185 self->m_resolvers.emplace(
188 grblAxis, modeSettingId,
189 units::value_t{units::steps_per_turn, -1.0}});
192 ctx.edge->getDrv()->reg_map->motion_core.res_angle, i, 0,
195 ctx.edge->getDrv()->reg_map->motion_core.res_step, i, 0, 32};
196 ctx.registers[uid + s_resolverMonitorSuffix +
"/diff"] =
RegInfo{
197 ctx.edge->getDrv()->reg_map->motion_core.res_drv_diff, i, 0,
199 ctx.registers[uid + s_resolverMonitorSuffix +
201 ctx.edge->getDrv()->reg_map->motion_core.res_drv_diff_max,
203 ctx.registers[uid + s_resolverMonitorSuffix +
"/slost/gcr"] =
204 RegInfo{ctx.edge->getDrv()->reg_map->motion_core.res_gcr,
205 24, uint32_t(1 << i), 32};
206 ctx.registers[uid + s_resolverMonitorSuffix +
"/slost/gsr"] =
207 RegInfo{ctx.edge->getDrv()->reg_map->motion_core.res_gsr, 0,
208 uint32_t(1 << i), 32};
209 cmd.prom->get<
void>().set_value();
211 if (f.wait_for(milliseconds(3000)) != std::future_status::ready)
214 <<
"Failed to create registers for position sensor: "
222 pos->getConfig(s_modeSettingName).wait();
230 if (deviceType.count(DeviceType::AXIS_POSITION_MONITOR))
232 if (!deviceType.count(DeviceType::AXIS))
233 error(s_loggerCat) <<
"Can't probe for AxisPositionMonitor objects "
234 "when Axis are not probed";
235 else if (!deviceType.count(DeviceType::POSITION_SENSOR))
236 error(s_loggerCat) <<
"Can't probe for AxisPositionMonitor objects "
237 "when Position are not probed";
242 void MFEPlatform::generateGpios(Context &ctx, std::list<DeviceBase::Shared> &ret)
244 const std::string platformUrl = ctx.prefix + ctx.id +
"/gpio";
246 ret.emplace_back(std::make_shared<MFEEdgeGpio>(platformUrl +
"/dinput",
247 shared_from_this()));
248 ctx.registers[ret.back()->uid()] =
RegInfo{
249 ctx.edge->getDrv()->reg_map->motion_core.dinr, 0, 0, 32};
251 ret.emplace_back(std::make_shared<MFEEdgeGpio>(platformUrl +
"/limit",
252 shared_from_this()));
253 ctx.registers[ret.back()->uid()] =
RegInfo{
254 ctx.edge->getDrv()->reg_map->grbl_gpio.lir, 0, 0, 32};
256 ret.emplace_back(std::make_shared<MFEEdgeGpio>(
257 platformUrl +
"/driver/ready", shared_from_this()));
258 ctx.registers[ret.back()->uid()] =
RegInfo{
259 ctx.edge->getDrv()->reg_map->motion_core.dinr, 18, 0, 8};
261 ret.emplace_back(std::make_shared<MFEEdgeGpio>(
262 platformUrl +
"/driver/enable", shared_from_this()));
263 ctx.registers[ret.back()->uid()] =
RegInfo{
264 ctx.edge->getDrv()->reg_map->grbl_gpio.en, 0, 0, 8};
269 [&axisCount](GrblPlatform::Shared &,
const GrblPlatform::Context &ctx) {
270 axisCount = ctx.binfo.axisCount;
274 for (
size_t i = 0; i < axisCount; ++i)
276 const grbl::Axis grblAxis =
static_cast<grbl::Axis
>(i);
277 ret.emplace_back(std::make_shared<MFEEdgeGpio>(
279 shared_from_this()));
280 ctx.registers[ret.back()->uid()] =
RegInfo{
281 ctx.edge->getDrv()->reg_map->grbl_gpio.lir, i, 0x01, 1};
283 ret.emplace_back(std::make_shared<MFEEdgeGpio>(
285 shared_from_this()));
286 ctx.registers[ret.back()->uid()] =
RegInfo{
287 ctx.edge->getDrv()->reg_map->grbl_gpio.lir, i + 8, 0x01, 1};
289 ret.emplace_back(std::make_shared<MFEEdgeGpio>(
291 shared_from_this()));
292 ctx.registers[ret.back()->uid()] =
RegInfo{
293 ctx.edge->getDrv()->reg_map->motion_core.dinr, i + 18, 0x01, 1};
295 ret.emplace_back(std::make_shared<MFEEdgeGpio>(
297 shared_from_this()));
298 ctx.registers[ret.back()->uid()] =
RegInfo{
299 ctx.edge->getDrv()->reg_map->grbl_gpio.en, i, 0x01, 1};
309 <<
"edge device not available, not updating devices";
315 std::set<DeviceId> notifications;
316 size_t resolverCount;
318 std::lock_guard<std::mutex> guard(m_mutex);
319 resolverCount = m_resolvers.size();
324 debug(s_loggerCat) <<
"updating resolvers";
325 std::vector<uint32_t> angles(resolverCount, 0);
326 std::vector<uint32_t> steps(resolverCount, 0);
327 std::vector<uint32_t> diff(resolverCount, 0);
331 ctx.edge->read(ctx.edge->getDrv()->reg_map->motion_core.res_angle,
333 ctx.edge->read(ctx.edge->getDrv()->reg_map->motion_core.res_step,
336 ctx.edge->getDrv()->reg_map->motion_core.res_drv_diff, diff);
337 ctx.edge->read(ctx.edge->getDrv()->reg_map->motion_core.res_gsr,
339 ctx.edge->read(ctx.edge->getDrv()->reg_map->motion_core.res_gcr,
343 std::lock_guard<std::mutex> guard(m_mutex);
344 for (
auto &it : m_resolvers)
346 size_t index = size_t(it.second.grblAxis);
347 if (index >= resolverCount)
350 <<
"invalid index for resolver: " << index;
353 AxisPositionMonitor::State state;
354 const uint8_t axis_bit = 1 << index;
355 if (resGCR & (axis_bit << 24))
356 state = AxisPositionMonitor::State::DISABLED;
357 else if (resGSR & axis_bit)
358 state = AxisPositionMonitor::State::TRIGGERED;
360 state = AxisPositionMonitor::State::ENABLED;
362 if (steps[index] != it.second.stepReg)
363 notifications.insert(it.first);
364 it.second.stepReg = steps[index];
365 it.second.angleReg = angles[index];
367 if (state != it.second.monitorState)
370 <<
"resolver step-lost state changed: " << it.first
372 notifications.insert(it.first + s_resolverMonitorSuffix);
374 it.second.monitorState = state;
375 it.second.diffReg = diff[index];
381 notify(std::move(notifications));
383 catch (
const std::exception &ex)
385 error(s_loggerCat) <<
"MFEPlatform error: " << ex.what();
388 MGrblPlatform::processUpdate(ctx);
391 MFEPlatform::Context::Context(
const ccut::yml::NodeRef &ref) :
398 std::map<std::string, RegInfo>::const_iterator it{registers.find(uid)};
400 if (it == registers.cend())
408 const std::string &uid)
const
410 std::map<std::string, ResolverInfo>::const_iterator it{
411 m_resolvers.find(uid)};
412 if (it == m_resolvers.cend())
413 throw Exception(ErrorCode::InvalidArguments,
414 "invalid position object: " + uid);
421 std::lock_guard<std::mutex> l(m_lock);
422 return _getResolverInfo(uid).grblAxis;
427 const std::string resolverUid = uid.substr(
428 0, uid.length() - s_resolverMonitorSuffix.length());
433 grbl::SettingId settingId,
434 const std::string &value)
436 std::unique_lock<std::mutex> l(m_lock);
437 std::map<std::string, ResolverInfo>::iterator it{m_resolvers.find(uid)};
438 if (it == m_resolvers.cend())
439 throw Exception(ErrorCode::InvalidArguments,
440 "invalid position object: " + uid);
442 if (settingId == it->second.modeSettingId)
444 it->second.mode.value = std::stof(value);
447 info(s_loggerCat) <<
"updating resolver " << uid <<
" mode: " << value;
451 units::value_t MFEPlatform::getResolverPosition(
const std::string &uid,
452 const units::unit_t unit)
const
454 std::lock_guard<std::mutex> l(m_lock);
460 double(*
reinterpret_cast<const int32_t *
>(
461 &_getResolverInfo(uid).stepReg))};
465 return units::value_t{
467 *
reinterpret_cast<const float *
>(
reinterpret_cast<const void *
>(
468 &_getResolverInfo(uid).angleReg))};
471 throw Exception(ErrorCode::IncompatibleUnits,
472 "failed to convert position");
476 units::value_t MFEPlatform::getResolverMode(
const std::string &uid)
const
478 std::lock_guard<std::mutex> l(m_lock);
479 return _getResolverInfo(uid).
mode;
482 MFEAxisPositionMonitor::State MFEPlatform::getResolverMonitorState(
483 const std::string &uid,
486 std::lock_guard<std::mutex> l(m_lock);
487 const ResolverInfo &info = _getResolverInfo(uid);
489 return info.monitorState;
Exception thrown by MotionController in case of issues with command.
const std::string & to_string(Axis::State state)
convert State to string
main motion-lib namespace
bool getRegInfo(const std::string &uid, RegInfo &info) const
Get the RegInfo object.