Instrument Neutral Distributed Interface INDI  2.0.2
celestrondriver.h
Go to the documentation of this file.
1 /*
2  Celestron driver
3 
4  Copyright (C) 2015 Jasem Mutlaq
5  Copyright (C) 2017 Juan Menendez
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public
9  License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21 
22 /*
23  Version with experimental pulse guide support. GC 04.12.2015
24 */
25 
26 #pragma once
27 
28 #include <string>
29 #include "indicom.h"
30 
31 #include <stdint.h>
32 
33 //#include <thread>
34 //#include <condition_variable>
35 //#include <atomic>
36 
37 /* Starsense specific constants */
38 #define ISNEXSTAR 0x11
39 #define ISSTARSENSE 0x13
40 #define MINSTSENSVER 1.18
41 #define MAX_RESP_SIZE 20
42 
43 // device IDs
44 #define CELESTRON_DEV_RA 0x10
45 #define CELESTRON_DEV_DEC 0x11
46 #define CELESTRON_DEV_GPS 0xb0
47 // focuser device
48 #define CELESTRON_DEV_FOC 0x12
49 
50 // motor commands
51 #define MC_GET_POSITION 0x01 // return 24 bit position
52 #define MC_GOTO_FAST 0x02 // send 24 bit target
53 #define MC_SET_POS_GUIDERATE 0x06 // use the 2 byte CelestronTrackRates to set the rate
54 #define MC_SET_NEG_GUIDERATE 0x07 // for Southern hemisphere, track mode EQ_S
55 #define MC_LEVEL_START 0x0b // move to switch position
56 #define MC_PEC_RECORD_START 0x0C // n/a Ack Start recording PEC position
57 #define MC_PEC_PLAYBACK 0x0D // 8 bits Ack Start(01)/stop(00) PEC playback
58 
59 #define MTR_PECBIN 0x0E // current PEC index - 1 byte 0 - 255(88)
60 
61 #define MC_LEVEL_DONE 0x12 // return 0xFF when move finished
62 #define MC_SLEW_DONE 0x13 // return 0xFF when move finished
63 #define MC_PEC_RECORD_DONE 0x15 // n/a 8 bits != 0 is PEC record completed
64 #define MC_PEC_RECORD_STOP 0x16 // n/a n/a Stop PEC recording
65 
66 #define MC_GOTO_SLOW 0x17 // 16/24 bits Ack Goto position with slow, variable rate. Either 16 or 24 bit accuracy.
67 // Position is a signed fraction of a full rotation
68 #define MC_AT_INDEX 0x18 // n/a 8 bits FFH at index, 00H not
69 #define MC_SEEK_INDEX 0x19 // n/a n/a Seek PEC Index
70 #define MC_MOVE_POS 0x24 // start move positive direction, rate 0-9, 0 is stop
71 #define MC_MOVE_NEG 0x25 // start move negative direction, rate 0-9, 0 is stop
72 
73 #define MTR_AUX_GUIDE 0x26 // aux guide command, rate -100 to 100, duration centiseconds
74 #define MTR_IS_AUX_GUIDE_ACTIVE 0x27 // return 0x00 when aux guide is not in progress
75 
76 // command 0x30 and 0x31 are read/ write memory commands
77 #define MC_PEC_READ_DATA 0x30 // 8 PEC data value return 1 byte of data:
78 // 0x3f number of PEC bins (88)
79 // 0x40+i PEC data for bin i
80 #define MC_PEC_WRITE_DATA 0x31 // 16 PEC data address, PEC data value
81 // 0x40+i, value bin i
82 
83 #define MC_SET_AUTOGUIDE_RATE 0x46 // 0 to 99 as % sidereal
84 #define MC_GET_AUTOGUIDE_RATE 0x47 // 0 to 99 as % sidereal
85 
86 // focuser passthrough commands
87 #define FOC_CALIB_ENABLE 42 // send 0 to start or 1 to stop
88 #define FOC_CALIB_DONE 43 // returns 2 bytes [0] done, [1] state 0-12
89 #define FOC_GET_HS_POSITIONS 44 // returns 2 ints, low and high limits
90 
91 // generic device commands
92 #define GET_VER 0xfe // return 2 or 4 bytes major.minor.build
93 
97 typedef enum { RA_AXIS, DEC_AXIS } CELESTRON_AXIS;
100 
101 
102 // PEC state machine
103 // the order matters because it's used to check what states are available.
104 // they do not match the the base TelescopePECState
105 typedef enum
106 {
107  NotKnown, // PEC has not been checked.
108 
113 
119 
124 
130 
136 
141 
143 
144 // These values are sent to the hour angle axis motor using the MC_SET_POS|NEG_GUIDERATE
145 // commands to set the tracking rate.
146 typedef enum
147 {
148  CTR_SIDEREAL = 0xFFFF,
149  CTR_SOLAR = 0xFFFE,
150  CTR_LUNAR = 0xFFFD
152 
153 typedef struct
154 {
155  std::string Model;
156  std::string Version;
157  //std::string GPSFirmware;
158  std::string RAFirmware;
159  std::string DEFirmware;
162  bool isGem;
163  bool canPec;
167 } FirmwareInfo;
168 
169 typedef struct SimData
170 {
171  double ra;
172  double dec;
173  double az;
174  double alt;
178  bool isSlewing;
179  uint32_t foc_position = 20000;
180  uint32_t foc_target = 20000;
182 
183 
184 /**************************************************************************
185  Utility functions
186 **************************************************************************/
187 namespace Celestron
188 {
189 double trimDecAngle(double angle);
190 uint16_t dd2nex(double angle);
191 uint32_t dd2pnex(double angle);
192 double nex2dd(uint32_t value);
193 double pnex2dd(uint32_t value);
194 }
195 
197 {
198  public:
200  virtual ~CelestronDriver() = default;
201 
202  // Misc.
203  const char *getDeviceName();
204  void set_port_fd(int port_fd)
205  {
206  fd = port_fd;
207  }
208  void set_simulation(bool enable)
209  {
210  simulation = enable;
211  }
212  void set_device(const char *name);
213 
214  // Simulation
216  {
217  sim_data.slewRate = val;
218  }
220  {
221  sim_data.trackMode = val;
222  }
224  {
225  sim_data.gpsStatus = val;
226  }
227  void set_sim_slewing(bool isSlewing)
228  {
229  sim_data.isSlewing = isSlewing;
230  }
231  void set_sim_ra(double ra)
232  {
233  sim_data.ra = ra;
234  }
235  void set_sim_dec(double dec)
236  {
237  sim_data.dec = dec;
238  }
239  void set_sim_az(double az)
240  {
241  sim_data.az = az;
242  }
243  void set_sim_alt(double alt)
244  {
245  sim_data.alt = alt;
246  }
247  double get_sim_ra()
248  {
249  return sim_data.ra;
250  }
251  double get_sim_dec()
252  {
253  return sim_data.dec;
254  }
256  {
258  }
259  void move_sim_foc(int offset)
260  {
261  sim_data.foc_position += offset;
262  }
263 
264  bool echo();
265  bool check_connection();
266 
267  // Get info
268  bool get_firmware(FirmwareInfo *info);
269  bool get_version(char *version, size_t size);
270  bool get_variant(char *variant);
271  int model(); // returns model number, -1 if failed
272  bool get_model(char *model, size_t size, bool *isGem, bool *canPec, bool *hasHomeIndex);
273  bool get_dev_firmware(int dev, char *version, size_t size);
274  bool get_radec(double *ra, double *dec, bool precise);
275  bool get_azalt(double *az, double *alt, bool precise);
276  bool get_utc_date_time(double *utc_hours, int *yy, int *mm, int *dd, int *hh, int *minute, int *ss, bool *dst,
277  bool precise);
278 
279  // Motion
282  bool abort();
283  bool slew_radec(double ra, double dec, bool precise);
284  bool slew_azalt(double az, double alt, bool precise);
285  bool sync(double ra, double dec, bool precise);
286  bool unsync();
287 
288  // Time & Location
289  bool set_location(double longitude, double latitude);
290  bool get_location(double* longitude, double *latitude);
291  bool set_datetime(struct ln_date *utc, double utc_offset, bool dst = false, bool precise = false);
292 
293  // Track Mode, this is not the Indi track mode
296 
297  bool is_slewing(bool *slewing);
298 
299  // Hibernate/Wakeup/ align
300  bool hibernate();
301  bool wakeup();
302  bool lastalign();
303  bool startmovetoindex();
304  bool indexreached(bool *atIndex);
305 
306  // Pulse Guide
307  size_t send_pulse(CELESTRON_DIRECTION direction, unsigned char rate, unsigned char duration_msec);
308  bool get_pulse_status(CELESTRON_DIRECTION direction);
309 
310  // get and set guide rate
311  // 0 to 255 corresponding to 0 to 100% sidereal
312  bool get_guide_rate(CELESTRON_AXIS axis, uint8_t * rate);
313  bool set_guide_rate(CELESTRON_AXIS axis, uint8_t rate);
314 
315  // Pointing state, pier side, returns 'E' or 'W'
316  bool get_pier_side(char * sop);
317 
318  // check if the mount is aligned using the mount J command
319  bool check_aligned(bool *isAligned);
320 
321  // set the tracking rate, sidereal, solar or lunar
323 
324  // focuser commands
325  bool foc_exists(); // read version
326  int foc_position(); // read position, return -1 if failed
327  bool foc_move(uint32_t steps); // start move
328  bool foc_moving(); // return true if moving
329  bool foc_limits(int * low, int * high); // read limits
330  bool foc_abort(); // stop move
331 
332  // PEC management
333 
335 
337 
338  bool PecSeekIndex();
339  bool isPecAtIndex(bool force = false); // returns true if the PEC index has been found
340 
341  size_t pecIndex(); // reads the current PEC index
342  int getPecValue(size_t index); // reads the current PEC value
343  bool setPecValue(size_t index, int data);
344 
345  bool PecPlayback(bool start);
346 
347  bool PecRecord(bool start);
348  bool isPecRecordDone();
349 
350  size_t getPecNumBins();
351 
352  const char *PecStateStr(PEC_STATE);
353  const char *PecStateStr();
354 
355  // PEC simulation properties
356  int simIndex;
358  bool simSeekIndex = false;
359 
360  protected:
361  void set_sim_response(const char *fmt, ...);
362  virtual int serial_write(const char *cmd, int nbytes, int *nbytes_written);
363  virtual int serial_read(int nbytes, int *nbytes_read);
364  virtual int serial_read_section(char stop_char, int *nbytes_read);
365 
366  size_t send_command(const char *cmd, size_t cmd_len, char *resp, size_t resp_len,
367  bool ascii_cmd, bool ascii_resp);
368  size_t send_passthrough(int dest, int cmd_id, const char *payload,
369  size_t payload_len, char *resp, size_t response_len);
370 
372  bool simulation = false;
374  int fd = 0;
375 
376  char sim_ra_guide_rate = 50;
378 };
379 
380 class PecData
381 {
382  public:
383  PecData();
384 
385  // save PEC data to a file
386  bool Save(const char * filename);
387 
388  // saves PEC data to mount
389  bool Save(CelestronDriver * driver);
390 
391  // Loads PEC data from mount
392  bool Load(CelestronDriver * driver);
393 
394  // Loads PEC data from file
395  bool Load(const char * fileName);
396 
397  size_t NumBins()
398  {
399  return numBins;
400  }
401 
402  void RemoveDrift();
403 
404  const char *getDeviceName();
405  // void set_device(const char *name);
406 
407  private:
408  double wormArcSeconds = 7200;
409  double rateScale = 1024;
410  size_t numBins = 88;
411  const double SIDEREAL_ARCSEC_PER_SEC = 360.0 * 60.0 * 60.0 / (23.0 * 3600.0 + 56 * 60 + 4.09);
412 
413  double data[255]; // numbins + 1 values, accumulated PEC offset in arc secs. First one zero
414 
415  void Kalman(PecData newData, int num);
416 };
417 
418 
CELESTRON_DIRECTION
@ CELESTRON_W
@ CELESTRON_N
@ CELESTRON_S
@ CELESTRON_E
CELESTRON_FIRMWARE
@ FW_CAN_AUX
@ FW_MODEL
@ FW_ISGEM
@ FW_VERSION
@ FW_DEC
@ FW_HAS_FOC
@ FW_RA
CELESTRON_SLEW_RATE
@ SR_1
@ SR_6
@ SR_8
@ SR_5
@ SR_4
@ SR_9
@ SR_2
@ SR_7
@ SR_3
struct SimData SimData
CELESTRON_TRACK_MODE
@ CTM_EQN
@ CTM_ALTAZ
@ CTM_EQS
@ CTM_OFF
@ CTM_RADEC
#define MAX_RESP_SIZE
CELESTRON_TRACK_RATE
@ CTR_SIDEREAL
@ CTR_SOLAR
@ CTR_LUNAR
PEC_STATE
@ NotKnown
@ PEC_SEEKING
The PEC index is being searched for, goes to PEC_INDEXED when found
@ PEC_AVAILABLE
PEC is available but inactive, can seek index Seek index is only available command
@ PEC_PLAYBACK
PEC is being played back, stays in this state until stopped equivalent to TelescopePECState PEC_ON
@ PEC_RECORDING
PEC is being recorded, goes to PEC_INDEXED when completed
@ PEC_NOT_AVAILABLE
PEC is not available, hardware has been checked, no other state is possible
@ PEC_INDEXED
the PEC index has been found, can go to Playback or Recording this is equivalent to TelescopePECState...
CELESTRON_AXIS
@ DEC_AXIS
@ RA_AXIS
CELESTRON_GPS_STATUS
@ GPS_OFF
@ GPS_ON
bool slew_radec(double ra, double dec, bool precise)
bool get_azalt(double *az, double *alt, bool precise)
bool set_guide_rate(CELESTRON_AXIS axis, uint8_t rate)
void set_port_fd(int port_fd)
bool indexreached(bool *atIndex)
bool check_aligned(bool *isAligned)
void set_sim_alt(double alt)
bool set_datetime(struct ln_date *utc, double utc_offset, bool dst=false, bool precise=false)
bool set_location(double longitude, double latitude)
bool stop_motion(CELESTRON_DIRECTION dir)
int getPecValue(size_t index)
void set_sim_track_mode(CELESTRON_TRACK_MODE val)
bool get_firmware(FirmwareInfo *info)
bool sync(double ra, double dec, bool precise)
bool foc_limits(int *low, int *high)
bool PecPlayback(bool start)
bool get_dev_firmware(int dev, char *version, size_t size)
size_t send_pulse(CELESTRON_DIRECTION direction, unsigned char rate, unsigned char duration_msec)
size_t send_passthrough(int dest, int cmd_id, const char *payload, size_t payload_len, char *resp, size_t response_len)
bool get_radec(double *ra, double *dec, bool precise)
bool get_track_mode(CELESTRON_TRACK_MODE *mode)
void move_sim_foc(int offset)
void set_device(const char *name)
void set_simulation(bool enable)
bool set_track_rate(CELESTRON_TRACK_RATE rate, CELESTRON_TRACK_MODE mode)
bool set_track_mode(CELESTRON_TRACK_MODE mode)
void set_sim_az(double az)
bool get_model(char *model, size_t size, bool *isGem, bool *canPec, bool *hasHomeIndex)
bool get_version(char *version, size_t size)
size_t send_command(const char *cmd, size_t cmd_len, char *resp, size_t resp_len, bool ascii_cmd, bool ascii_resp)
char response[MAX_RESP_SIZE]
virtual int serial_read(int nbytes, int *nbytes_read)
const char * PecStateStr()
void set_sim_gps_status(CELESTRON_GPS_STATUS val)
void set_sim_response(const char *fmt,...)
virtual ~CelestronDriver()=default
bool PecRecord(bool start)
bool isPecAtIndex(bool force=false)
bool get_variant(char *variant)
bool get_location(double *longitude, double *latitude)
void set_sim_ra(double ra)
const char * getDeviceName()
bool get_pulse_status(CELESTRON_DIRECTION direction)
void set_sim_slewing(bool isSlewing)
virtual int serial_write(const char *cmd, int nbytes, int *nbytes_written)
PEC_STATE updatePecState()
virtual int serial_read_section(char stop_char, int *nbytes_read)
bool get_guide_rate(CELESTRON_AXIS axis, uint8_t *rate)
void set_sim_dec(double dec)
bool slew_azalt(double az, double alt, bool precise)
void set_sim_slew_rate(CELESTRON_SLEW_RATE val)
bool setPecValue(size_t index, int data)
bool foc_move(uint32_t steps)
bool get_pier_side(char *sop)
bool is_slewing(bool *slewing)
bool get_utc_date_time(double *utc_hours, int *yy, int *mm, int *dd, int *hh, int *minute, int *ss, bool *dst, bool precise)
bool start_motion(CELESTRON_DIRECTION dir, CELESTRON_SLEW_RATE rate)
PecData()
PecData class.
const char * getDeviceName()
size_t NumBins()
void RemoveDrift()
bool Load(CelestronDriver *driver)
bool Save(const char *filename)
double ra
double dec
Implementations for common driver routines.
double pnex2dd(uint32_t value)
uint32_t dd2pnex(double angle)
uint16_t dd2nex(double angle)
double trimDecAngle(double angle)
double nex2dd(uint32_t value)
struct FirmwareInfo FirmwareInfo
__u8 cmd[4]
Definition: pwc-ioctl.h:2
double controllerVersion
std::string Version
std::string RAFirmware
CELESTRON_TRACK_MODE celestronTrackMode
std::string Model
std::string DEFirmware
CELESTRON_SLEW_RATE slewRate
double alt
uint32_t foc_position
CELESTRON_GPS_STATUS gpsStatus
double dec
CELESTRON_TRACK_MODE trackMode
bool isSlewing
uint32_t foc_target