#include "asibfm700_hardware.h" using namespace asibfm700; /* error category implementation */ const char* AsibFM700HardwareErrorCategory::name() const noexcept { return "ASTROSIB FM700 MOUNT HARDWARE ERROR CATEGORY"; } std::string AsibFM700HardwareErrorCategory::message(int ec) const { AsibFM700HardwareErrorCode code = static_cast(ec); std::string msg; switch (code) { case AsibFM700HardwareErrorCode::ERROR_OK: msg = "OK"; case asibfm700::AsibFM700HardwareErrorCode::ERROR_FATAL: msg = "fatal hardware error"; case AsibFM700HardwareErrorCode::ERROR_BADFORMAT: msg = "wrong arguments of function"; case AsibFM700HardwareErrorCode::ERROR_ENCODERDEV: msg = "encoder device error or can't open"; case AsibFM700HardwareErrorCode::ERROR_MOUNTDEV: msg = "mount device error or can't open"; case AsibFM700HardwareErrorCode::ERROR_FAILED: msg = "failed to run command - protocol error"; default: msg = "UNKNOWN ERROR"; } return msg; } const AsibFM700HardwareErrorCategory& AsibFM700HardwareErrorCategory::get() { static const AsibFM700HardwareErrorCategory constInst; return constInst; } /* AsibFM700Hardware CLASS IMPLEMENTATION */ /* static methods */ // void AsibFM700Hardware::moveInst(AsibFM700Hardware* from, AsibFM700Hardware* to) // { // to->_hwConfig = std::move(from->_hwConfig); // to->_deviceConfig = std::move(from->_deviceConfig); // from->_deviceConfig.MountDevPath = nullptr; // from->_deviceConfig.EncoderDevPath = nullptr; // from->_deviceConfig.EncoderXDevPath = nullptr; // from->_deviceConfig.EncoderYDevPath = nullptr; // } /* constructors and destructor */ AsibFM700Hardware::AsibFM700Hardware(const hardware_config_t& conf) : _hardwareConfig(conf), _sideralRate2(_hardwareConfig.hwConfig.eqrate) { _hardwareConfig.devConfig.MountDevPath = const_cast(_hardwareConfig.MountDevPath.c_str()); _hardwareConfig.devConfig.EncoderDevPath = const_cast(_hardwareConfig.EncoderDevPath.c_str()); _hardwareConfig.devConfig.EncoderXDevPath = const_cast(_hardwareConfig.EncoderXDevPath.c_str()); _hardwareConfig.devConfig.EncoderYDevPath = const_cast(_hardwareConfig.EncoderYDevPath.c_str()); _sideralRate2 *= _sideralRate2; _sideralRateEps2 = 0.01; // 1% // start state polling _statePollingThread = std::jthread([this](std::stop_token stoken) { mountdata_t data; while (true) { if (stoken.stop_requested()) { return; } error_t err = static_cast(Mount.getMountData(&data)); if (err == AsibFM700HardwareErrorCode::ERROR_OK) { // are both motors stopped? bool stop_motors = (data.extradata.ExtraBits & XMOTOR_STOP_BIT) && (data.extradata.ExtraBits & YMOTOR_STOP_BIT); if (stop_motors) { _state = hw_state_t::HW_STATE_STOP; } } } }); } // AsibFM700Hardware::AsibFM700Hardware(AsibFM700Hardware&& other) // { // moveInst(&other, this); // } // AsibFM700Hardware& AsibFM700Hardware::operator=(AsibFM700Hardware&& other) // { // moveInst(&other, this); // return *this; // } AsibFM700Hardware::~AsibFM700Hardware() {} std::string_view AsibFM700Hardware::id() const { return "Sidereal Technology Servo II controller"; } AsibFM700Hardware::error_t AsibFM700Hardware::getState(AsibFM700Hardware::hw_state_t& state) const { mountdata_t data; error_t err = static_cast(Mount.getMountData(&data)); if (err == AsibFM700HardwareErrorCode::ERROR_OK) { // are both motors stopped? bool stop_motors = (data.extradata.ExtraBits & XMOTOR_STOP_BIT) && (data.extradata.ExtraBits & YMOTOR_STOP_BIT); if (stop_motors) { state = hw_state_t::HW_STATE_STOP; return AsibFM700HardwareErrorCode::ERROR_OK; } // compute current speed auto rate2 = data.encXspeed.val * data.encXspeed.val + data.encYspeed.val * data.encYspeed.val; auto ratio2 = rate2 / _sideralRate2; if (ratio2 <= _sideralRateEps2) { // tracking state = hw_state_t::HW_STATE_TRACK; } else { state = hw_state_t::HW_STATE_SLEW; } } return err; } AsibFM700Hardware::error_t AsibFM700Hardware::setPos(AsibFM700Hardware::axes_pos_t pos) { error_t err; // according to"SiTech protocol notes" X is DEC-axis and Y is HA-axis coordpair_t hw_pos{.X = pos.y, .Y = pos.x}; if (!pos.flags.slewNguide) { return static_cast(Mount.slewTo(&hw_pos, pos.flags)); } switch (pos.state) { case hw_state_t::HW_STATE_SLEW: // slew mount err = static_cast(Mount.slewTo(&hw_pos, pos.flags)); break; case hw_state_t::HW_STATE_TRACK: // interpretate as guiding correction err = static_cast(Mount.correctBy(&hw_pos)); break; case hw_state_t::HW_STATE_STOP: break; default: break; } return err; } AsibFM700Hardware::error_t AsibFM700Hardware::getPos(AsibFM700Hardware::axes_pos_t& pos) { mountdata_t data; error_t err = static_cast(Mount.getMountData(&data)); if (err == AsibFM700HardwareErrorCode::ERROR_OK) { // time point from sidservo library is 'double' number represented UNIXTIME with // microseconds/nanoseconds precision (must be equal for encXposition and encYposition) using secs_t = std::chrono::duration; secs_t secs = secs_t{data.encXposition.t}; pos.time_point = time_point_t{std::chrono::duration_cast(secs)}; // according to "SiTech protocol notes" X is DEC-axis and Y is HA-axis pos.x = data.encYposition.val; pos.y = data.encXposition.val; pos.xrate = data.encYspeed.val; pos.yrate = data.encXspeed.val; // mount state err = getState(pos.state); } return err; } AsibFM700Hardware::error_t AsibFM700Hardware::stop() { auto err = static_cast(Mount.stop()); return err; } AsibFM700Hardware::error_t AsibFM700Hardware::init() { auto err = static_cast(Mount.init(&_hardwareConfig.devConfig)); return err; }