diff options
Diffstat (limited to 'indi-celestronaux/celestronaux.h')
-rw-r--r-- | indi-celestronaux/celestronaux.h | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/indi-celestronaux/celestronaux.h b/indi-celestronaux/celestronaux.h new file mode 100644 index 0000000..6a79280 --- /dev/null +++ b/indi-celestronaux/celestronaux.h @@ -0,0 +1,442 @@ +/* + Celestron Aux Mount Driver. + + Copyright (C) 2020 Paweł T. Jochym + Copyright (C) 2020 Fabrizio Pollastri + Copyright (C) 2020-2022 Jasem Mutlaq + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + JM 2022.07.07: Added Wedge support. +*/ + +#pragma once + +#include <indicom.h> +#include <indiguiderinterface.h> +#include <inditelescope.h> +#include <indielapsedtimer.h> +#include <connectionplugins/connectionserial.h> +#include <connectionplugins/connectiontcp.h> +#include <alignment/AlignmentSubsystemForDrivers.h> +#include <indipropertyswitch.h> +#include <indipropertynumber.h> +#include <indipropertytext.h> +#include <pid.h> +#include <termios.h> + +#include "auxproto.h" + +class CelestronAUX : + public INDI::Telescope, + public INDI::GuiderInterface, + public INDI::AlignmentSubsystem::AlignmentSubsystemForDrivers +{ + public: + CelestronAUX(); + ~CelestronAUX() override; + + virtual bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], + char *formats[], char *names[], int n) override; + virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override; + virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override; + virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override; + virtual bool ISSnoopDevice(XMLEle *root) override; + + // Type defs + enum ScopeStatus_t + { + IDLE, + SLEWING_FAST, + APPROACH, + SLEWING_SLOW, + SLEWING_MANUAL, + TRACKING + }; + ScopeStatus_t ScopeStatus; + + enum AxisStatus + { + STOPPED, + SLEWING + }; + + enum AxisDirection + { + FORWARD, + REVERSE + }; + + // Previous motion direction + // TODO: Switch to AltAz from N-S/W-E + typedef enum + { + PREVIOUS_NS_MOTION_NORTH = DIRECTION_NORTH, + PREVIOUS_NS_MOTION_SOUTH = DIRECTION_SOUTH, + PREVIOUS_NS_MOTION_UNKNOWN = -1 + } PreviousNSMotion_t; + typedef enum + { + PREVIOUS_WE_MOTION_WEST = DIRECTION_WEST, + PREVIOUS_WE_MOTION_EAST = DIRECTION_EAST, + PREVIOUS_WE_MOTION_UNKNOWN = -1 + } PreviousWEMotion_t; + + // Public to enable setting from ISSnoop + void syncCoordWrapPosition(); + + protected: + virtual void ISGetProperties(const char *dev) override; + virtual bool initProperties() override; + virtual bool updateProperties() override; + virtual bool saveConfigItems(FILE *fp) override; + virtual bool Handshake() override; + virtual bool Disconnect() override; + + virtual const char *getDefaultName() override; + INDI::IHorizontalCoordinates AltAzFromRaDec(double ra, double dec, double ts); + + virtual bool Sync(double ra, double dec) override; + virtual bool Goto(double ra, double dec) override; + virtual bool Abort() override; + virtual bool Park() override; + virtual bool UnPark() override; + + virtual IPState GuideNorth(uint32_t ms) override; + virtual IPState GuideSouth(uint32_t ms) override; + virtual IPState GuideEast(uint32_t ms) override; + virtual IPState GuideWest(uint32_t ms) override; + + //virtual bool HandleGetAutoguideRate(INDI_HO_AXIS axis, uint8_t rate); + //virtual bool HandleSetAutoguideRate(INDI_EQ_AXIS axis); + //virtual bool HandleGuidePulse(INDI_EQ_AXIS axis); + //virtual bool HandleGuidePulseDone(INDI_EQ_AXIS axis, bool done); + + // TODO: Switch to AltAz from N-S/W-E + virtual bool MoveNS(INDI_DIR_NS dir, TelescopeMotionCommand command) override; + virtual bool MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) override; + + virtual bool ReadScopeStatus() override; + virtual void TimerHit() override; + virtual bool updateLocation(double latitude, double longitude, double elevation) override; + + ///////////////////////////////////////////////////////////////////////////////////// + /// Motion Control + ///////////////////////////////////////////////////////////////////////////////////// + bool stopAxis(INDI_HO_AXIS axis); + bool isSlewing(); + + /** + * @brief SlewTo Go to a 24bit encoder position. + * @param axis AZ or ALT + * @param steps Encoder microsteps + * @param fast If true, use fast command to reach target. If false, use slow command. + * @return True if successful, false otherwise. + */ + bool slewTo(INDI_HO_AXIS axis, uint32_t steps, bool fast = true); + + /** + * @brief SlewByRate Slew an axis using variable rate speed. + * @param axis AZ or ALT + * @param rate -9 to +9. 0 means stop. + * For AZ, negative means left while positive means right. + * For Alt, negative is down while positive is up. + * @return True if successful, false otherwise. + */ + bool slewByRate(INDI_HO_AXIS axis, int8_t rate); + + // Go to index position or level + bool goHome(INDI_HO_AXIS axis); + bool isHomingDone(INDI_HO_AXIS axis); + bool m_HomingProgress[2] = {false, false}; + + ///////////////////////////////////////////////////////////////////////////////////// + /// Tracking + ///////////////////////////////////////////////////////////////////////////////////// + bool SetTrackEnabled(bool enabled) override; + bool SetTrackMode(uint8_t mode) override; + bool SetTrackRate(double raRate, double deRate) override; + void resetTracking(); + + /** + * @brief TrackByRate Set axis tracking rate in arcsecs/sec. + * @param axis AZ or ALT + * @param rate arcsecs/s. Zero would stop tracking. + * For AZ, negative means left while positive means right. + * For Alt, negative is down while positive is up. + * @return True if successful, false otherwise. + */ + bool trackByRate(INDI_HO_AXIS axis, int32_t rate); + + /** + * @brief trackByRate Track using specific mode (sidereal, solar, or lunar) + * @param axis AZ or ALT + * @param mode sidereal, solar, or lunar + * @return True if successful, false otherwise. + */ + bool trackByMode(INDI_HO_AXIS axis, uint8_t mode); + bool isTrackingRequested(); + + bool getStatus(INDI_HO_AXIS axis); + bool getEncoder(INDI_HO_AXIS axis); + + ///////////////////////////////////////////////////////////////////////////////////// + /// Coord Wrap + ///////////////////////////////////////////////////////////////////////////////////// + bool setCordWrapEnabled(bool enable); + bool getCordWrapEnabled(); + bool setCordWrapPosition(uint32_t steps); + uint32_t getCordWrapPosition(); + + private: + ///////////////////////////////////////////////////////////////////////////////////// + /// Misc + ///////////////////////////////////////////////////////////////////////////////////// + double getNorthAz(); + bool isNorthHemisphere() const + { + return m_Location.latitude >= 0; + } + bool getVersion(AUXTargets target); + void getVersions(); + void hex_dump(char *buf, AUXBuffer data, size_t size); + + + double AzimuthToDegrees(double degree); + double DegreesToAzimuth(double degree); + + double EncodersToDegrees(uint32_t steps); + uint32_t DegreesToEncoders(double degrees); + + double EncodersToHours(uint32_t steps); + uint32_t HoursToEncoders(double hour); + + double EncodersToDE(uint32_t steps, TelescopePierSide pierSide); + double DEToEncoders(double de); + + void EncodersToAltAz(INDI::IHorizontalCoordinates &coords); + void EncodersToRADE(INDI::IEquatorialCoordinates &coords, TelescopePierSide &pierSide); + void RADEToEncoders(const INDI::IEquatorialCoordinates &coords, uint32_t &haEncoder, uint32_t &deEncoder); + + /** + * @brief mountToSkyCoords Convert mount coordinates to equatorial sky coordinates + * @return True if successful, false otherwise. + * @note This works for both Alt-Az and Equatorial Mounts. + */ + bool mountToSkyCoords(); + ///////////////////////////////////////////////////////////////////////////////////// + /// Guiding + ///////////////////////////////////////////////////////////////////////////////////// + bool guidePulse(INDI_EQ_AXIS axis, uint32_t ms, int8_t rate); + + + private: + // Axis Information + AxisStatus m_AxisStatus[2] {STOPPED, STOPPED}; + AxisDirection m_AxisDirection[2] {FORWARD, FORWARD}; + + // Guiding offset in steps + // For each pulse, we modify the offset so that we can add it to our current tracking traget + int32_t m_GuideOffset[2] = {0, 0}; + double m_TrackRates[2] = {TRACKRATE_SIDEREAL, 0}; + + // approach distance + double Approach {1}; + TelescopePierSide m_TargetPierSide {PIER_UNKNOWN}; + + // Tracking targets + INDI::IEquatorialCoordinates m_SkyTrackingTarget { 0, 0 }; + INDI::IEquatorialCoordinates m_SkyGOTOTarget { 0, 0 }; + + // Actual Sky Equatorial Coordinates + INDI::IEquatorialCoordinates m_SkyCurrentRADE {0, 0}; + + // Current Mount Alt/Az or RA/DE + INDI::IEquatorialCoordinates m_MountCurrentRADE {0, 0}; + INDI::IHorizontalCoordinates m_MountCurrentAltAz {0, 0}; + + INDI::ElapsedTimer m_TrackingElapsedTimer; + + + ///////////////////////////////////////////////////////////////////////////////////// + /// Auxiliary Command Communication + ///////////////////////////////////////////////////////////////////////////////////// + bool sendAUXCommand(AUXCommand &command); + void closeConnection(); + void emulateGPS(AUXCommand &m); + bool serialReadResponse(AUXCommand c); + bool tcpReadResponse(); + bool readAUXResponse(AUXCommand c); + bool processResponse(AUXCommand &cmd); + int sendBuffer(AUXBuffer buf); + void formatVersionString(char *s, int n, uint8_t *verBuf); + + // GPS Emulation + bool m_GPSEmulation {false}; + + // Firmware + uint8_t m_MainBoardVersion[4] {0}; + uint8_t m_AltitudeVersion[4] {0}; + uint8_t m_AzimuthVersion[4] {0}; + uint8_t m_HCVersion[4] {0}; + uint8_t m_BATVersion[4] {0}; + uint8_t m_WiFiVersion[4] {0}; + uint8_t m_GPSVersion[4] {0}; + + // Coord Wrap + bool m_CordWrapActive {false}; + int32_t m_CordWrapPosition {0}; + uint32_t m_RequestedCordwrapPos; + + // Manual Slewing NSWE + bool m_ManualMotionActive { false }; + + // Debug + uint32_t DBG_CAUX {0}; + uint32_t DBG_SERIAL {0}; + + /////////////////////////////////////////////////////////////////////////////// + /// Communication + /////////////////////////////////////////////////////////////////////////////// + int m_ModemControl {0}; + void setRTS(bool rts); + bool waitCTS(float timeout); + bool detectRTSCTS(); + bool detectHC(char *version, size_t size); + int response_data_size; + int aux_tty_read(char *buf, int bufsiz, int timeout, int *n); + int aux_tty_write (char *buf, int bufsiz, float timeout, int *n); + bool tty_set_speed(speed_t speed); + + // connection + bool m_IsRTSCTS {false}; + bool m_isHandController {false}; + + /////////////////////////////////////////////////////////////////////////////// + /// Celestron AUX Properties + /////////////////////////////////////////////////////////////////////////////// + + // Firmware + INDI::PropertyText FirmwareTP {7}; + enum {FW_HC, FW_MB, FW_AZM, FW_ALT, FW_WiFi, FW_BAT, FW_GPS}; + // Mount type + INDI::PropertySwitch MountTypeSP {2}; + enum + { + MOUNT_EQUATORIAL, + MOUNT_ALTAZ + }; + + // Mount Cord wrap Toogle + INDI::PropertySwitch CordWrapToggleSP {2}; + + // Mount Coord wrap Position + INDI::PropertySwitch CordWrapPositionSP {4}; + enum { CORDWRAP_N, CORDWRAP_E, CORDWRAP_S, CORDWRAP_W }; + + // Cordwrap base (0-encoder/True directions) + // Use 0-encoders / Sky directions as base for parking and cordwrap + INDI::PropertySwitch CordWrapBaseSP {2}; + enum {CW_BASE_ENC, CW_BASE_SKY}; + + // GPS emulator + INDI::PropertySwitch GPSEmuSP {2}; + enum { GPSEMU_OFF, GPSEMU_ON }; + + // Horizontal Coords + INDI::PropertyNumber HorizontalCoordsNP {2}; + + // Guide Rate + INDI::PropertyNumber GuideRateNP {2}; + + // Encoders + INDI::PropertyNumber EncoderNP {2}; + // Angles + INDI::PropertyNumber AngleNP {2}; + + int32_t m_LastTrackRate[2] = {-1, -1}; + double m_TrackStartSteps[2] = {0, 0}; + double m_LastOffset[2] = {0, 0}; + uint8_t m_OffsetSwitchSettle[2] = {0, 0}; + bool m_IsWedge {false}; + + // PID controllers + INDI::PropertyNumber Axis1PIDNP {3}; + INDI::PropertyNumber Axis2PIDNP {3}; + enum + { + Propotional, + Derivative, + Integral + }; + + std::unique_ptr<PID> m_Controllers[2]; + + INDI::PropertySwitch PortTypeSP {2}; + enum + { + PORT_AUX_PC, + PORT_HC_USB, + }; + + int m_ConfigPortType {PORT_AUX_PC}; + + // Home/Level + INDI::PropertySwitch HomeSP {3}; + enum + { + HOME_AXIS1, + HOME_AXIS2, + HOME_ALL + }; + //INDI::PropertyNumber GainNP {2}; + /////////////////////////////////////////////////////////////////////////////// + /// Static Const Private Variables + /////////////////////////////////////////////////////////////////////////////// + + private: + + // One definition rule (ODR) constants + // AUX commands use 24bit integer as a representation of angle in units of + // fractional revolutions. Thus 2^24 steps makes full revolution. + static constexpr int32_t STEPS_PER_REVOLUTION {16777216}; + static constexpr double STEPS_PER_DEGREE {STEPS_PER_REVOLUTION / 360.0}; + static constexpr double STEPS_PER_ARCSEC {STEPS_PER_DEGREE / 3600.0}; + static constexpr double DEGREES_PER_STEP {360.0 / STEPS_PER_REVOLUTION}; + + static constexpr double STEPS_PER_HOUR {STEPS_PER_REVOLUTION / 24.0}; + static constexpr double HOURS_PER_STEP {24.0 / STEPS_PER_REVOLUTION}; + + // Measured rate that would result in 1 step/sec + static constexpr uint32_t GAIN_STEPS {80}; + + // MC_SET_POS_GUIDERATE & MC_SET_NEG_GUIDERATE use 24bit number rate in + static constexpr uint8_t RATE_PER_ARCSEC {4}; + + static constexpr uint32_t BUFFER_SIZE {10240}; + // seconds + static constexpr uint8_t READ_TIMEOUT {1}; + // ms + static constexpr uint8_t CTS_TIMEOUT {100}; + // Coord Wrap + static constexpr const char *CORDWRAP_TAB {"Coord Wrap"}; + static constexpr const char *MOUNTINFO_TAB {"Mount Info"}; + // Track modes + static constexpr uint16_t AUX_SIDEREAL {0xffff}; + static constexpr uint16_t AUX_SOLAR {0xfffe}; + static constexpr uint16_t AUX_LUNAR {0xfffd}; + + +}; |