#pragma once /* MOUNT CONTROL COMPONENTS LIBRARY */ #include #include #include #include #include #include #include "spdlog/sinks/null_sink.h" // low-level functions namespace lowlevel { #include "../LibSidServo/sidservo.h" } // namespace lowlevel namespace mcc { enum class MccMountType : uint8_t { GERMAN_TYPE, FORK_TYPE, CROSSAXIS_TYPE, ALTAZ_TYPE }; // mount state type concept template concept mcc_mount_state_c = requires(T t, const T t_const) { { t_const.ident() } -> std::same_as; { t.enter() } -> std::same_as; { t.exit() } -> std::same_as; }; // implements a Finite State Machine Pattern template class MccMount { typedef double mnt_coord_t; typedef double mnt_speed_t; typedef double time_point_t; public: static constexpr MccMountType mountType = MOUNT_TYPE; /* low-level hardware related constants */ // number of attempts to get low-level hardware data before emit an error static constexpr uint8_t LOWLEVEL_HW_POLL_ATTEMPTS = 10; /* mount main-cycle variable quantities (mount orientation) */ struct mount_orient_t { // time-related std::chrono::system_clock::time_point utc; time_point_t mjd; // modified Julian date time_point_t siderTime; // sideral time (in radians) // apparent target (user-input) current coordinates (in radians) mnt_coord_t tagRA, tagDEC; mnt_coord_t tagHA; mnt_coord_t tagAZ, tagZD; // encoder-measured current mount coordinates (in radians) mnt_coord_t mntRA, mntDEC; mnt_coord_t mntHA; mnt_coord_t mntAZ, mntZD; // encoder-measured current mount moving speed (in radians/s) mnt_speed_t mntSpeedX, mntSpeedY; // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one // current refraction coefficient mnt_coord_t currRefr; // PCS (pointing correction system) corrections mnt_coord_t pcsX, pcsY; // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one // mount current state }; struct mount_config_t { uint8_t hw_poll_attempts = LOWLEVEL_HW_POLL_ATTEMPTS; }; MccMount(std::shared_ptr logger = spdlog::null_logger_mt("NULL")) : _mountLogger(logger), _exitCurrentState([]() {}) { } virtual ~MccMount() {} template void setMountState(StateT& state) { _exitCurrentState(); // exit from current state _exitCurrentState = [&state]() { state.exit(); }; state.enter(); } mount_orient_t getMountData() const noexcept { return _currentMountOrient.load(); } protected: mount_config_t _mountCurrentConfig; std::shared_ptr _mountLogger; std::function _exitCurrentState; std::atomic _currentMountOrient; void updateMountState() { mount_orient_t orient; lowlevel::mountdata_t hw_mdata; // get data from encoders decltype(mount_config_t::hw_poll_attempts) n_attempts = 0; do { auto ret_code = lowlevel::Mount.getMountData(&hw_mdata); if (ret_code != lowlevel::MCC_E_OK) { ++n_attempts; } } while (n_attempts < _mountCurrentConfig.hw_poll_attempts); if (n_attempts >= _mountCurrentConfig.hw_poll_attempts) { // log error heres return; } _currentMountOrient.store(orient); } }; } // namespace mcc