You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1387 lines
27 KiB
1387 lines
27 KiB
#if 0
|
|
LX200 Driver
|
|
Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
|
|
|
|
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
|
|
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <math.h>
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <termios.h>
|
|
#include <time.h>
|
|
|
|
#include "indicom.h"
|
|
#include "indidevapi.h"
|
|
#include "lx200driver.h"
|
|
|
|
#define LX200_TIMEOUT 5 /* FD timeout in seconds */
|
|
|
|
int fd;
|
|
int read_ret, write_ret;
|
|
|
|
/**************************************************************************
|
|
Basic I/O
|
|
**************************************************************************/
|
|
int openPort(const char *portID);
|
|
int portRead(char *buf, int nbytes, int timeout);
|
|
int portWrite(const char * buf);
|
|
int LX200readOut(int timeout);
|
|
|
|
int Connect(const char* device);
|
|
void Disconnect(void);
|
|
|
|
/**************************************************************************
|
|
Diagnostics
|
|
**************************************************************************/
|
|
char ACK(void);
|
|
int testTelescope(void);
|
|
int testAP(void);
|
|
|
|
/**************************************************************************
|
|
Get Commands: store data in the supplied buffer. Return 0 on success or -1 on failure
|
|
**************************************************************************/
|
|
|
|
/* Get Double from Sexagisemal */
|
|
int getCommandSexa(double *value, const char *cmd);
|
|
/* Get String */
|
|
int getCommandString(char *data, const char* cmd);
|
|
/* Get Int */
|
|
int getCommandInt(int *value, const char* cmd);
|
|
/* Get tracking frequency */
|
|
int getTrackFreq(double * value);
|
|
/* Get site Latitude */
|
|
int getSiteLatitude(int *dd, int *mm);
|
|
/* Get site Longitude */
|
|
int getSiteLongitude(int *ddd, int *mm);
|
|
/* Get Calender data */
|
|
int getCalenderDate(char *date);
|
|
/* Get site Name */
|
|
int getSiteName(char *siteName, int siteNum);
|
|
/* Get Number of Bars */
|
|
int getNumberOfBars(int *value);
|
|
/* Get Home Search Status */
|
|
int getHomeSearchStatus(int *status);
|
|
/* Get OTA Temperature */
|
|
int getOTATemp(double * value);
|
|
/* Get time format: 12 or 24 */
|
|
int getTimeFormat(int *format);
|
|
|
|
|
|
/**************************************************************************
|
|
Set Commands
|
|
**************************************************************************/
|
|
|
|
/* Set Int */
|
|
int setCommandInt(int data, const char *cmd);
|
|
/* Set Sexigesimal */
|
|
int setCommandXYZ( int x, int y, int z, const char *cmd);
|
|
/* Common routine for Set commands */
|
|
int setStandardProcedure(char * writeData);
|
|
/* Set Slew Mode */
|
|
int setSlewMode(int slewMode);
|
|
/* Set Alignment mode */
|
|
int setAlignmentMode(unsigned int alignMode);
|
|
/* Set Object RA */
|
|
int setObjectRA(double ra);
|
|
/* set Object DEC */
|
|
int setObjectDEC(double dec);
|
|
/* Set Calender date */
|
|
int setCalenderDate(int dd, int mm, int yy);
|
|
/* Set UTC offset */
|
|
int setUTCOffset(double hours);
|
|
/* Set Track Freq */
|
|
int setTrackFreq(double trackF);
|
|
/* Set current site longitude */
|
|
int setSiteLongitude(double Long);
|
|
/* Set current site latitude */
|
|
int setSiteLatitude(double Lat);
|
|
/* Set Object Azimuth */
|
|
int setObjAz(double az);
|
|
/* Set Object Altitude */
|
|
int setObjAlt(double alt);
|
|
/* Set site name */
|
|
int setSiteName(char * siteName, int siteNum);
|
|
/* Set maximum slew rate */
|
|
int setMaxSlewRate(int slewRate);
|
|
/* Set focuser motion */
|
|
int setFocuserMotion(int motionType);
|
|
/* Set focuser speed mode */
|
|
int setFocuserSpeedMode (int speedMode);
|
|
/* Set minimum elevation limit */
|
|
int setMinElevationLimit(int min);
|
|
/* Set maximum elevation limit */
|
|
int setMaxElevationLimit(int max);
|
|
|
|
/**************************************************************************
|
|
Motion Commands
|
|
**************************************************************************/
|
|
/* Slew to the selected coordinates */
|
|
int Slew(void);
|
|
/* Synchronize to the selected coordinates and return the matching object if any */
|
|
int Sync(char *matchedObject);
|
|
/* Abort slew in all axes */
|
|
int abortSlew(void);
|
|
/* Move into one direction, two valid directions can be stacked */
|
|
int MoveTo(int direction);
|
|
/* Half movement in a particular direction */
|
|
int HaltMovement(int direction);
|
|
/* Select the tracking mode */
|
|
int selectTrackingMode(int trackMode);
|
|
/* Select Astro-Physics tracking mode */
|
|
int selectAPTrackingMode(int trackMode);
|
|
|
|
/**************************************************************************
|
|
Other Commands
|
|
**************************************************************************/
|
|
/* Ensures LX200 RA/DEC format is long */
|
|
int checkLX200Format(void);
|
|
/* Select a site from the LX200 controller */
|
|
int selectSite(int siteNum);
|
|
/* Select a catalog object */
|
|
int selectCatalogObject(int catalog, int NNNN);
|
|
/* Select a sub catalog */
|
|
int selectSubCatalog(int catalog, int subCatalog);
|
|
|
|
/**********************************************************************
|
|
* BASIC
|
|
**********************************************************************/
|
|
|
|
int Connect(const char *device)
|
|
{
|
|
fprintf(stderr, "Connecting to device %s\n", device);
|
|
|
|
if (openPort(device) < 0)
|
|
return -1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
void Disconnect()
|
|
{
|
|
fprintf(stderr, "Disconnected.\n");
|
|
close(fd);
|
|
}
|
|
|
|
int testTelescope()
|
|
{
|
|
int i=0;
|
|
char ack[1] = { (char) 0x06 };
|
|
char MountAlign[64];
|
|
fprintf(stderr, "Testing telescope's connection...\n");
|
|
|
|
for (i=0; i < 2; i++)
|
|
{
|
|
write(fd, ack, 1);
|
|
read_ret = portRead(MountAlign, 1, LX200_TIMEOUT);
|
|
if (read_ret == 1)
|
|
return 0;
|
|
usleep(50000);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int testAP()
|
|
{
|
|
int i=0;
|
|
char currentDate[64];
|
|
|
|
fprintf(stderr, "Testing telescope's connection...\n");
|
|
|
|
/* We need to test if the telescope is responding
|
|
/ We're going to request the calander date */
|
|
for (i=0; i < 2; i++)
|
|
{
|
|
if (!getCalenderDate(currentDate))
|
|
return 0;
|
|
|
|
usleep(50000);
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* GET
|
|
**********************************************************************/
|
|
|
|
char ACK()
|
|
{
|
|
char ack[1] = { (char) 0x06 };
|
|
char MountAlign[2];
|
|
|
|
write_ret = write(fd, ack, 1);
|
|
|
|
if (write_ret < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(MountAlign, 1, LX200_TIMEOUT);
|
|
|
|
if (read_ret == 1)
|
|
return MountAlign[0];
|
|
else
|
|
return read_ret;
|
|
|
|
}
|
|
|
|
int getCommandSexa(double *value, const char * cmd)
|
|
{
|
|
char tempString[16];
|
|
|
|
tcflush(fd, TCIFLUSH);
|
|
|
|
if (portWrite(cmd) < 0)
|
|
return -1;
|
|
|
|
if ( (read_ret = portRead(tempString, -1, LX200_TIMEOUT)) < 1)
|
|
return read_ret;
|
|
|
|
tempString[read_ret - 1] = '\0';
|
|
|
|
if (f_scansexa(tempString, value))
|
|
{
|
|
fprintf(stderr, "unable to process [%s]\n", tempString);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int getCommandString(char *data, const char* cmd)
|
|
{
|
|
char * term;
|
|
|
|
if (portWrite(cmd) < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(data, -1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
term = strchr (data, '#');
|
|
if (term)
|
|
*term = '\0';
|
|
|
|
fprintf(stderr, "Requested data: %s\n", data);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int getCalenderDate(char *date)
|
|
{
|
|
|
|
int dd, mm, yy;
|
|
int err;
|
|
|
|
if ( (err = getCommandString(date, "#:GC#")) )
|
|
return err;
|
|
|
|
/* Meade format is MM/DD/YY */
|
|
|
|
read_ret = sscanf(date, "%d%*c%d%*c%d", &mm, &dd, &yy);
|
|
if (read_ret < 3)
|
|
return -1;
|
|
|
|
/* We need to have in in YYYY/MM/DD format */
|
|
sprintf(date, "20%02d/%02d/%02d", yy, mm, dd);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
int getTimeFormat(int *format)
|
|
{
|
|
char tempString[16];
|
|
int tMode;
|
|
|
|
if (portWrite("#:Gc#") < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(tempString, -1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
tempString[read_ret-1] = '\0';
|
|
|
|
read_ret = sscanf(tempString, "(%d)", &tMode);
|
|
|
|
if (read_ret < 1)
|
|
return -1;
|
|
else
|
|
*format = tMode;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*int getUTCOffset()
|
|
{
|
|
char tempString[4];
|
|
int offSet;
|
|
|
|
portWrite("#:GG#");
|
|
|
|
read_ret = portRead(tempString, 4);
|
|
if (read_ret)
|
|
return -1;
|
|
|
|
tempString[3] = '\0';
|
|
|
|
sscanf(tempString, "%d", &offSet);
|
|
|
|
fprintf(stderr, "UTC Offset: %d\n", offSet);
|
|
|
|
return offSet;
|
|
}
|
|
|
|
int getMaxElevationLimit()
|
|
{
|
|
char tempString[16];
|
|
int limit;
|
|
|
|
portWrite("#:Go#");
|
|
|
|
read_ret = portRead(tempString, -1, LX200_TIMEOUT);
|
|
if (read_ret < 1)
|
|
return -1;
|
|
|
|
tempString[read_ret-1] = '\0';
|
|
|
|
sscanf(tempString, "%d", &limit);
|
|
|
|
fprintf(stderr, "Max elevation limit string is %s\n", tempString);
|
|
|
|
return limit;
|
|
}
|
|
|
|
int getMinElevationLimit()
|
|
{
|
|
char tempString[16];
|
|
int limit;
|
|
|
|
portWrite("#:Gh#");
|
|
|
|
read_ret = portRead(tempString, -1, LX200_TIMEOUT);
|
|
if (read_ret < 1)
|
|
return -1;
|
|
|
|
tempString[read_ret-1] = '\0';
|
|
|
|
sscanf(tempString, "%d", &limit);
|
|
|
|
fprintf(stderr, "Min elevation limit string is %s\n", tempString);
|
|
|
|
return limit;
|
|
|
|
}
|
|
*/
|
|
|
|
int getSiteName(char *siteName, int siteNum)
|
|
{
|
|
char * term;
|
|
|
|
switch (siteNum)
|
|
{
|
|
case 1:
|
|
if (portWrite("#:GM#") < 0)
|
|
return -1;
|
|
break;
|
|
case 2:
|
|
if (portWrite("#:GN#") < 0)
|
|
return -1;
|
|
break;
|
|
case 3:
|
|
if (portWrite("#:GO#") < 0)
|
|
return -1;
|
|
break;
|
|
case 4:
|
|
if (portWrite("#:GP#") < 0)
|
|
return -1;
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
read_ret = portRead(siteName, -1, LX200_TIMEOUT);
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
siteName[read_ret - 1] = '\0';
|
|
|
|
term = strchr (siteName, ' ');
|
|
if (term)
|
|
*term = '\0';
|
|
|
|
term = strchr (siteName, '<');
|
|
if (term)
|
|
strcpy(siteName, "unused site");
|
|
|
|
fprintf(stderr, "Requested site name: %s\n", siteName);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int getSiteLatitude(int *dd, int *mm)
|
|
{
|
|
char tempString[16];
|
|
|
|
if (portWrite("#:Gt#") < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(tempString, -1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
tempString[read_ret -1] = '\0';
|
|
|
|
if (sscanf (tempString, "%d%*c%d", dd, mm) < 2)
|
|
return -1;
|
|
|
|
fprintf(stderr, "Requested site latitude in String %s\n", tempString);
|
|
fprintf(stderr, "Requested site latitude %d:%d\n", *dd, *mm);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int getSiteLongitude(int *ddd, int *mm)
|
|
{
|
|
char tempString[16];
|
|
|
|
if (portWrite("#:Gg#") < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(tempString, -1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
tempString[read_ret -1] = '\0';
|
|
|
|
if (sscanf (tempString, "%d%*c%d", ddd, mm) < 2)
|
|
return -1;
|
|
|
|
fprintf(stderr, "Requested site longitude in String %s\n", tempString);
|
|
fprintf(stderr, "Requested site longitude %d:%d\n", *ddd, *mm);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int getTrackFreq(double *value)
|
|
{
|
|
float Freq;
|
|
char tempString[16];
|
|
|
|
if (portWrite("#:GT#") < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(tempString, -1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
tempString[read_ret] = '\0';
|
|
|
|
/*fprintf(stderr, "Telescope tracking freq str: %s\n", tempString);*/
|
|
|
|
if (sscanf(tempString, "%f#", &Freq) < 1)
|
|
return -1;
|
|
|
|
*value = (double) Freq;
|
|
|
|
/*fprintf(stderr, "Tracking frequency value is %f\n", Freq);*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
int getNumberOfBars(int *value)
|
|
{
|
|
char tempString[128];
|
|
|
|
if (portWrite("#:D#") < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(tempString, -1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 0)
|
|
return read_ret;
|
|
|
|
*value = read_ret -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int getHomeSearchStatus(int *status)
|
|
{
|
|
char tempString[16];
|
|
|
|
if (portWrite("#:h?#") < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(tempString, 1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
tempString[1] = '\0';
|
|
|
|
if (tempString[0] == '0')
|
|
*status = 0;
|
|
else if (tempString[0] == '1')
|
|
*status = 1;
|
|
else if (tempString[0] == '2')
|
|
*status = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int getOTATemp(double *value)
|
|
{
|
|
|
|
char tempString[16];
|
|
float temp;
|
|
|
|
if (portWrite("#:fT#") < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(tempString, -1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
tempString[read_ret - 1] = '\0';
|
|
|
|
if (sscanf(tempString, "%f", &temp) < 1)
|
|
return -1;
|
|
|
|
*value = (double) temp;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int updateSkyCommanderCoord(double *ra, double *dec)
|
|
{
|
|
char coords[16];
|
|
char CR[1] = { (char) 0x0D };
|
|
float RA=0.0, DEC=0.0;
|
|
|
|
write(fd, CR, 1);
|
|
|
|
read_ret = portRead(coords, 16, LX200_TIMEOUT);
|
|
|
|
read_ret = sscanf(coords, " %g %g", &RA, &DEC);
|
|
|
|
if (read_ret < 2)
|
|
{
|
|
fprintf(stderr, "Error in Sky commander number format [%s], exiting.\n", coords);
|
|
return -1;
|
|
}
|
|
|
|
*ra = RA;
|
|
*dec = DEC;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* SET
|
|
**********************************************************************/
|
|
|
|
int setStandardProcedure(char * data)
|
|
{
|
|
char boolRet[2];
|
|
|
|
if (portWrite(data) < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(boolRet, 1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
if (boolRet[0] == '0')
|
|
{
|
|
fprintf(stderr, "%s Failed.\n", data);
|
|
return -1;
|
|
}
|
|
|
|
fprintf(stderr, "%s Successful\n", data);
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
int setCommandInt(int data, const char *cmd)
|
|
{
|
|
|
|
char tempString[16];
|
|
|
|
snprintf(tempString, sizeof( tempString ), "%s%d#", cmd, data);
|
|
|
|
if (portWrite(tempString) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int setMinElevationLimit(int min)
|
|
{
|
|
char tempString[16];
|
|
|
|
snprintf(tempString, sizeof( tempString ), "#:Sh%02d#", min);
|
|
|
|
return (setStandardProcedure(tempString));
|
|
}
|
|
|
|
int setMaxElevationLimit(int max)
|
|
{
|
|
char tempString[16];
|
|
|
|
snprintf(tempString, sizeof( tempString ), "#:So%02d*#", max);
|
|
|
|
return (setStandardProcedure(tempString));
|
|
|
|
}
|
|
|
|
int setMaxSlewRate(int slewRate)
|
|
{
|
|
|
|
char tempString[16];
|
|
|
|
if (slewRate < 2 || slewRate > 8)
|
|
return -1;
|
|
|
|
snprintf(tempString, sizeof( tempString ), "#:Sw%d#", slewRate);
|
|
|
|
return (setStandardProcedure(tempString));
|
|
|
|
}
|
|
|
|
|
|
int setObjectRA(double ra)
|
|
{
|
|
|
|
int h, m, s;
|
|
char tempString[16];
|
|
|
|
getSexComponents(ra, &h, &m, &s);
|
|
|
|
snprintf(tempString, sizeof( tempString ), "#:Sr %02d:%02d:%02d#", h, m, s);
|
|
IDLog("Set Object RA String %s\n", tempString);
|
|
return (setStandardProcedure(tempString));
|
|
}
|
|
|
|
|
|
int setObjectDEC(double dec)
|
|
{
|
|
int d, m, s;
|
|
char tempString[16];
|
|
|
|
getSexComponents(dec, &d, &m, &s);
|
|
|
|
/* case with negative zero */
|
|
if (!d && dec < 0)
|
|
snprintf(tempString, sizeof( tempString ), "#:Sd -%02d:%02d:%02d#", d, m, s);
|
|
else
|
|
snprintf(tempString, sizeof( tempString ), "#:Sd %+03d:%02d:%02d#", d, m, s);
|
|
|
|
IDLog("Set Object DEC String %s\n", tempString);
|
|
|
|
return (setStandardProcedure(tempString));
|
|
|
|
}
|
|
|
|
int setCommandXYZ(int x, int y, int z, const char *cmd)
|
|
{
|
|
char tempString[16];
|
|
|
|
snprintf(tempString, sizeof( tempString ), "%s %02d:%02d:%02d#", cmd, x, y, z);
|
|
|
|
return (setStandardProcedure(tempString));
|
|
}
|
|
|
|
int setAlignmentMode(unsigned int alignMode)
|
|
{
|
|
fprintf(stderr , "Set alignment mode %d\n", alignMode);
|
|
|
|
switch (alignMode)
|
|
{
|
|
case LX200_ALIGN_POLAR:
|
|
if (portWrite("#:AP#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_ALIGN_ALTAZ:
|
|
if (portWrite("#:AA#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_ALIGN_LAND:
|
|
if (portWrite("#:AL#") < 0)
|
|
return -1;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int setCalenderDate(int dd, int mm, int yy)
|
|
{
|
|
char tempString[32];
|
|
char dumpPlanetaryUpdateString[64];
|
|
char boolRet[2];
|
|
yy = yy % 100;
|
|
|
|
snprintf(tempString, sizeof( tempString ), "#:SC %02d/%02d/%02d#", mm, dd, yy);
|
|
|
|
if (portWrite(tempString) < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(boolRet, 1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
boolRet[1] = '\0';
|
|
|
|
if (boolRet[0] == '0')
|
|
return -1;
|
|
|
|
/* Read dumped data */
|
|
portRead(dumpPlanetaryUpdateString, -1, LX200_TIMEOUT);
|
|
portRead(dumpPlanetaryUpdateString, -1, 5);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int setUTCOffset(double hours)
|
|
{
|
|
char tempString[16];
|
|
|
|
/*TODO add fractions*/
|
|
snprintf(tempString, sizeof( tempString ), "#:SG %+03d#", (int) hours);
|
|
|
|
fprintf(stderr, "UTC string is %s\n", tempString);
|
|
|
|
return (setStandardProcedure(tempString));
|
|
|
|
}
|
|
|
|
int setSiteLongitude(double Long)
|
|
{
|
|
int d, m, s;
|
|
char tempString[32];
|
|
|
|
getSexComponents(Long, &d, &m, &s);
|
|
|
|
snprintf(tempString, sizeof( tempString ), "#:Sg%03d:%02d#", d, m);
|
|
|
|
return (setStandardProcedure(tempString));
|
|
}
|
|
|
|
int setSiteLatitude(double Lat)
|
|
{
|
|
int d, m, s;
|
|
char tempString[32];
|
|
|
|
getSexComponents(Lat, &d, &m, &s);
|
|
|
|
snprintf(tempString, sizeof( tempString ), "#:St%+03d:%02d:%02d#", d, m, s);
|
|
|
|
return (setStandardProcedure(tempString));
|
|
}
|
|
|
|
int setObjAz(double az)
|
|
{
|
|
int d,m,s;
|
|
char tempString[16];
|
|
|
|
getSexComponents(az, &d, &m, &s);
|
|
|
|
snprintf(tempString, sizeof( tempString ), "#:Sz%03d:%02d#", d, m);
|
|
|
|
return (setStandardProcedure(tempString));
|
|
|
|
}
|
|
|
|
int setObjAlt(double alt)
|
|
{
|
|
int d, m, s;
|
|
char tempString[16];
|
|
|
|
getSexComponents(alt, &d, &m, &s);
|
|
|
|
snprintf(tempString, sizeof( tempString ), "#:Sa%+02d*%02d#", d, m);
|
|
|
|
return (setStandardProcedure(tempString));
|
|
}
|
|
|
|
|
|
int setSiteName(char * siteName, int siteNum)
|
|
{
|
|
|
|
char tempString[16];
|
|
|
|
switch (siteNum)
|
|
{
|
|
case 1:
|
|
snprintf(tempString, sizeof( tempString ), "#:SM %s#", siteName);
|
|
break;
|
|
case 2:
|
|
snprintf(tempString, sizeof( tempString ), "#:SN %s#", siteName);
|
|
break;
|
|
case 3:
|
|
snprintf(tempString, sizeof( tempString ), "#:SO %s#", siteName);
|
|
break;
|
|
case 4:
|
|
snprintf(tempString, sizeof( tempString ), "#:SP %s#", siteName);
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
return (setStandardProcedure(tempString));
|
|
}
|
|
|
|
int setSlewMode(int slewMode)
|
|
{
|
|
|
|
switch (slewMode)
|
|
{
|
|
case LX200_SLEW_MAX:
|
|
if (portWrite("#:RS#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_SLEW_FIND:
|
|
if (portWrite("#:RM#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_SLEW_CENTER:
|
|
if (portWrite("#:RC#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_SLEW_GUIDE:
|
|
if (portWrite("#:RG#") < 0)
|
|
return -1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int setFocuserMotion(int motionType)
|
|
{
|
|
|
|
switch (motionType)
|
|
{
|
|
case LX200_FOCUSIN:
|
|
if (portWrite("#:F+#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_FOCUSOUT:
|
|
if (portWrite("#:F-#") < 0)
|
|
return -1;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int setFocuserSpeedMode (int speedMode)
|
|
{
|
|
|
|
switch (speedMode)
|
|
{
|
|
case LX200_HALTFOCUS:
|
|
if (portWrite("#:FQ#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_FOCUSSLOW:
|
|
if (portWrite("#:FS#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_FOCUSMEDIUM:
|
|
if (portWrite("#:F3#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_FOCUSFAST:
|
|
if (portWrite("#:FF#") < 0)
|
|
return -1;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int setTrackFreq(double trackF)
|
|
{
|
|
char tempString[16];
|
|
|
|
snprintf(tempString, sizeof( tempString ), "#:ST %04.1f#", trackF);
|
|
|
|
return (setStandardProcedure(tempString));
|
|
|
|
}
|
|
|
|
/**********************************************************************
|
|
* Misc
|
|
*********************************************************************/
|
|
|
|
int Slew()
|
|
{
|
|
char slewNum[2];
|
|
char errorMsg[128];
|
|
|
|
if (portWrite("#:MS#") < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(slewNum, 1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
slewNum[1] = '\0';
|
|
|
|
if (slewNum[0] == '0')
|
|
return 0;
|
|
|
|
read_ret = portRead(errorMsg, -1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
if (slewNum[0] == '1')
|
|
return 1;
|
|
else return 2;
|
|
|
|
}
|
|
|
|
int MoveTo(int direction)
|
|
{
|
|
|
|
switch (direction)
|
|
{
|
|
case LX200_NORTH:
|
|
portWrite("#:Mn#");
|
|
break;
|
|
case LX200_WEST:
|
|
portWrite("#:Mw#");
|
|
break;
|
|
case LX200_EAST:
|
|
portWrite("#:Me#");
|
|
break;
|
|
case LX200_SOUTH:
|
|
portWrite("#:Ms#");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int HaltMovement(int direction)
|
|
{
|
|
|
|
switch (direction)
|
|
{
|
|
case LX200_NORTH:
|
|
if (portWrite("#:Qn#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_WEST:
|
|
if (portWrite("#:Qw#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_EAST:
|
|
if (portWrite("#:Qe#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_SOUTH:
|
|
if (portWrite("#:Qs#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_ALL:
|
|
if (portWrite("#:Q#") < 0)
|
|
return -1;
|
|
break;
|
|
default:
|
|
return -1;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int abortSlew()
|
|
{
|
|
if (portWrite("#:Q#") < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Sync(char *matchedObject)
|
|
{
|
|
portWrite("#:CM#");
|
|
|
|
read_ret = portRead(matchedObject, -1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
matchedObject[read_ret-1] = '\0';
|
|
|
|
/* Sleep 10ms before flushing. This solves some issues with LX200 compatible devices. */
|
|
usleep(10000);
|
|
|
|
tcflush(fd, TCIFLUSH);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int selectSite(int siteNum)
|
|
{
|
|
|
|
switch (siteNum)
|
|
{
|
|
case 1:
|
|
if (portWrite("#:W1#") < 0)
|
|
return -1;
|
|
break;
|
|
case 2:
|
|
if (portWrite("#:W2#") < 0)
|
|
return -1;
|
|
break;
|
|
case 3:
|
|
if (portWrite("#:W3#") < 0)
|
|
return -1;
|
|
break;
|
|
case 4:
|
|
if (portWrite("#:W4#") < 0)
|
|
return -1;
|
|
break;
|
|
default:
|
|
return -1;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int selectCatalogObject(int catalog, int NNNN)
|
|
{
|
|
char tempString[16];
|
|
|
|
switch (catalog)
|
|
{
|
|
case LX200_STAR_C:
|
|
snprintf(tempString, sizeof( tempString ), "#:LS%d#", NNNN);
|
|
break;
|
|
case LX200_DEEPSKY_C:
|
|
snprintf(tempString, sizeof( tempString ), "#:LC%d#", NNNN);
|
|
break;
|
|
case LX200_MESSIER_C:
|
|
snprintf(tempString, sizeof( tempString ), "#:LM%d#", NNNN);
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
if (portWrite(tempString) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int selectSubCatalog(int catalog, int subCatalog)
|
|
{
|
|
char tempString[16];
|
|
switch (catalog)
|
|
{
|
|
case LX200_STAR_C:
|
|
snprintf(tempString, sizeof( tempString ), "#:LsD%d#", subCatalog);
|
|
break;
|
|
case LX200_DEEPSKY_C:
|
|
snprintf(tempString, sizeof( tempString ), "#:LoD%d#", subCatalog);
|
|
break;
|
|
case LX200_MESSIER_C:
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
return (setStandardProcedure(tempString));
|
|
}
|
|
|
|
int checkLX200Format()
|
|
{
|
|
|
|
char tempString[16];
|
|
|
|
if (portWrite("#:GR#") < 0)
|
|
return -1;
|
|
|
|
read_ret = portRead(tempString, -1, LX200_TIMEOUT);
|
|
|
|
if (read_ret < 1)
|
|
return read_ret;
|
|
|
|
tempString[read_ret - 1] = '\0';
|
|
|
|
/* Short */
|
|
if (tempString[5] == '.')
|
|
if (portWrite("#:U#") < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int selectTrackingMode(int trackMode)
|
|
{
|
|
|
|
switch (trackMode)
|
|
{
|
|
case LX200_TRACK_DEFAULT:
|
|
fprintf(stderr, "Setting tracking mode to sidereal.\n");
|
|
if (portWrite("#:TQ#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_TRACK_LUNAR:
|
|
fprintf(stderr, "Setting tracking mode to LUNAR.\n");
|
|
if (portWrite("#:TL#") < 0)
|
|
return -1;
|
|
break;
|
|
case LX200_TRACK_MANUAL:
|
|
fprintf(stderr, "Setting tracking mode to CUSTOM.\n");
|
|
if (portWrite("#:TM#") < 0)
|
|
return -1;
|
|
break;
|
|
default:
|
|
return -1;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int selectAPTrackingMode(int trackMode)
|
|
{
|
|
switch (trackMode)
|
|
{
|
|
/* Lunar */
|
|
case 0:
|
|
fprintf(stderr, "Setting tracking mode to lunar.\n");
|
|
if (portWrite("#:RT0#") < 0)
|
|
return -1;
|
|
break;
|
|
|
|
/* Solar */
|
|
case 1:
|
|
fprintf(stderr, "Setting tracking mode to solar.\n");
|
|
if (portWrite("#:RT1#") < 0)
|
|
return -1;
|
|
break;
|
|
|
|
/* Sidereal */
|
|
case 2:
|
|
fprintf(stderr, "Setting tracking mode to sidereal.\n");
|
|
if (portWrite("#:RT2#") < 0)
|
|
return -1;
|
|
break;
|
|
|
|
/* Zero */
|
|
case 3:
|
|
fprintf(stderr, "Setting tracking mode to zero.\n");
|
|
if (portWrite("#:RT9#") < 0)
|
|
return -1;
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* Comm
|
|
**********************************************************************/
|
|
|
|
int openPort(const char *portID)
|
|
{
|
|
struct termios ttyOptions;
|
|
|
|
if ( (fd = open(portID, O_RDWR)) == -1)
|
|
return -1;
|
|
|
|
memset(&ttyOptions, 0, sizeof(ttyOptions));
|
|
tcgetattr(fd, &ttyOptions);
|
|
|
|
/* Control options
|
|
charecter size */
|
|
ttyOptions.c_cflag &= ~CSIZE;
|
|
/* 8 bit, enable read */
|
|
ttyOptions.c_cflag |= CREAD | CLOCAL | CS8;
|
|
/* no parity */
|
|
ttyOptions.c_cflag &= ~PARENB;
|
|
|
|
/* set baud rate */
|
|
cfsetispeed(&ttyOptions, B9600);
|
|
cfsetospeed(&ttyOptions, B9600);
|
|
|
|
/* set input/output flags */
|
|
ttyOptions.c_iflag = IGNBRK;
|
|
/* no software flow control */
|
|
ttyOptions.c_iflag &= ~(IXON|IXOFF|IXANY);
|
|
|
|
/* Read at least one byte */
|
|
ttyOptions.c_cc[VMIN] = 1;
|
|
ttyOptions.c_cc[VTIME] = 5;
|
|
|
|
/* Misc. */
|
|
ttyOptions.c_lflag = 0;
|
|
ttyOptions.c_oflag = 0;
|
|
|
|
/* set attributes */
|
|
tcsetattr(fd, TCSANOW, &ttyOptions);
|
|
|
|
/* flush the channel */
|
|
tcflush(fd, TCIOFLUSH);
|
|
return (fd);
|
|
}
|
|
|
|
int portWrite(const char * buf)
|
|
{
|
|
int nbytes, totalBytesWritten;
|
|
int bytesWritten = 0;
|
|
|
|
nbytes = totalBytesWritten = strlen(buf);
|
|
|
|
while (nbytes > 0)
|
|
{
|
|
|
|
bytesWritten = write(fd, buf, nbytes);
|
|
|
|
if (bytesWritten < 0)
|
|
return -1;
|
|
|
|
buf += bytesWritten;
|
|
nbytes -= bytesWritten;
|
|
}
|
|
|
|
/* Returns the # of bytes written */
|
|
return (totalBytesWritten);
|
|
}
|
|
|
|
int portRead(char *buf, int nbytes, int timeout)
|
|
{
|
|
|
|
int bytesRead = 0;
|
|
int totalBytesRead = 0;
|
|
int err;
|
|
|
|
/* Loop until encountring the '#' char */
|
|
if (nbytes == -1)
|
|
{
|
|
for (;;)
|
|
{
|
|
if ( (err = LX200readOut(timeout)) )
|
|
return err;
|
|
|
|
bytesRead = read(fd, buf, 1);
|
|
|
|
if (bytesRead < 0 )
|
|
return -1;
|
|
|
|
if (bytesRead)
|
|
totalBytesRead++;
|
|
|
|
if (*buf == '#')
|
|
return totalBytesRead;
|
|
|
|
buf += bytesRead;
|
|
}
|
|
}
|
|
|
|
while (nbytes > 0)
|
|
{
|
|
if ( (err = LX200readOut(timeout)) )
|
|
return err;
|
|
|
|
bytesRead = read(fd, buf, nbytes);
|
|
|
|
if (bytesRead < 0 )
|
|
return -1;
|
|
|
|
buf += bytesRead;
|
|
totalBytesRead++;
|
|
nbytes -= bytesRead;
|
|
}
|
|
|
|
return totalBytesRead;
|
|
}
|
|
|
|
int LX200readOut(int timeout)
|
|
{
|
|
struct timeval tv;
|
|
fd_set readout;
|
|
int retval;
|
|
|
|
FD_ZERO(&readout);
|
|
FD_SET(fd, &readout);
|
|
|
|
/* wait for 'timeout' seconds */
|
|
tv.tv_sec = timeout;
|
|
tv.tv_usec = 0;
|
|
|
|
/* Wait till we have a change in the fd status */
|
|
retval = select (fd+1, &readout, NULL, NULL, &tv);
|
|
|
|
/* Return 0 on successful fd change */
|
|
if (retval > 0)
|
|
return 0;
|
|
/* Return -1 due to an error */
|
|
else if (retval == -1)
|
|
return retval;
|
|
/* Return -2 if time expires before anything interesting happens */
|
|
else
|
|
return -2;
|
|
|
|
}
|
|
|