30 #define TEMMA_SLEW_RATES 2
31 #define TEMMA_TIMEOUT 5
32 #define TEMMA_BUFFER 64
33 #define TEMMA_SLEWRATE 5
42 static std::unique_ptr<TemmaMount> temma(
new TemmaMount());
46 SetTelescopeCapability(TELESCOPE_CAN_PARK |
50 TELESCOPE_CAN_CONTROL_TRACK |
51 TELESCOPE_HAS_TRACK_MODE |
53 TELESCOPE_HAS_LOCATION |
56 SetParkDataType(PARK_RA_DEC);
59 Longitude = std::numeric_limits<double>::quiet_NaN();
60 Latitude = std::numeric_limits<double>::quiet_NaN();
67 return "Temma Takahashi";
78 serialConnection->setParity(1);
82 setDriverInterface(getDriverInterface() | GUIDER_INTERFACE);
84 AddTrackMode(
"TRACK_SIDEREAL",
"Sidereal",
true);
85 AddTrackMode(
"TRACK_SOLAR",
"Solar");
89 InitAlignmentProperties(
this);
92 getSwitch(
"ALIGNMENT_SUBSYSTEM_ACTIVE")->sp[0].s =
ISS_ON;
122 if (strcmp(name, GuideNSNP.name) == 0 || strcmp(name, GuideWENP.name) == 0)
124 processGuiderProperties(name, values, names, n);
147 char *formats[],
char *names[],
int n)
174 TrackState = motorsEnabled() ? SCOPE_TRACKING : SCOPE_IDLE;
181 SetAxis1ParkDefault(
range24(lst + 3 / 60.0));
182 SetAxis2ParkDefault(Latitude >= 0 ? 90 : -90);
187 SetAxis1Park(
range24(lst + 3 / 60.0));
188 SetAxis2Park(Latitude >= 0 ? 90 : -90);
189 SetAxis1ParkDefault(
range24(lst + 3 / 60.0));
190 SetAxis2ParkDefault(Latitude >= 0 ? 90 : -90);
193 defineProperty(&GuideNSNP);
194 defineProperty(&GuideWENP);
197 loadConfig(
true,
"GEOGRAPHIC_COORD");
202 deleteProperty(GuideNSNP.name);
203 deleteProperty(GuideWENP.name);
209 bool TemmaMount::sendCommand(
const char *
cmd,
char *response)
211 int bytesWritten = 0, bytesRead = 0, rc = 0;
216 int cmd_size = strlen(cmd_temma);
223 cmd_temma[cmd_size] = 0xD;
224 cmd_temma[cmd_size + 1] = 0xA;
229 std::string
binary = std::bitset<8>(
cmd[1]).to_string();
237 if (response ==
nullptr)
249 if (TemmaInitialized ==
false || std::isnan(Longitude))
254 snprintf(response,
TEMMA_BUFFER,
"%02d%02d%02d", (
int)lst, ((
int)(lst * 60)) % 60, ((
int)(lst * 3600)) % 60);
272 if (TrackState == SCOPE_PARKED || TrackState == SCOPE_IDLE || TrackState == SCOPE_TRACKING)
275 ((
int)(
currentRA * (
double)6000)) % 100, sign, (
int)
dec, (
int)(
dec * (
double)60) % 60,
276 ((
int)(
dec * (
double)600)) % 10, state);
289 TrackState = SCOPE_SLEWING;
301 tcflush(PortFD, TCIOFLUSH);
304 if ( (rc =
tty_write(PortFD, cmd_temma, strlen(cmd_temma), &bytesWritten)) !=
TTY_OK)
312 if (response ==
nullptr)
324 tcflush(PortFD, TCIOFLUSH);
326 response[bytesRead - 2] = 0;
333 bool TemmaMount::getCoords()
337 bool rc = sendCommand(
"E", response);
341 if (response[0] !=
'E')
345 sscanf(response + 1,
"%02d%02d%02d", &d, &m, &s);
350 sscanf(response + 8,
"%02d%02d%01d", &d, &m, &s);
354 if(response[7] ==
'-')
357 char side = response[13];
361 setPierSide(PIER_EAST);
365 setPierSide(PIER_WEST);
370 if (strstr(response,
"F") !=
nullptr)
372 if (TrackState == SCOPE_SLEWING)
373 TrackState = SCOPE_TRACKING;
374 else if (TrackState == SCOPE_PARKING)
378 setMotorsEnabled(
false);
395 if (TemmaInitialized ==
false)
404 bool rc = getCoords();
414 if (IsAlignmentSubsystemActive())
416 const char *maligns[3] = {
"ZENITH",
"NORTH",
"SOUTH"};
417 double juliandate, lst;
421 juliandate = ln_get_julian_from_sys();
422 lst = ln_get_apparent_sidereal_time(juliandate) + (LocationN[1].value * 24.0 / 360.0);
424 RaDec.ra = ((lst -
currentRA) * 360.0) / 24.0;
430 "Status: Mnt. Algnt. %s LST %lf RA %lf DEC %lf HA %lf TDV(x %lf y %lf z %lf)",
435 if (!TransformTelescopeToCelestial(TDV, alignedRA, alignedDEC))
439 "Failed TransformTelescopeToCelestial: Scope RA=%g Scope DE=%f, Aligned RA=%f DE=%f",
currentRA,
currentDEC, alignedRA,
445 "TransformTelescopeToCelestial: Scope RA=%f Scope DE=%f, Aligned RA=%f DE=%f",
currentRA,
currentDEC, alignedRA,
450 if (!aligned && (syncdata.lst != 0.0))
452 DEBUGF(DBG_SCOPE_STATUS,
"Aligning with last sync delta RA %g DE %g", syncdata.deltaRA, syncdata.deltaDEC);
454 alignedRA += syncdata.deltaRA;
455 alignedDEC += syncdata.deltaDEC;
456 if (alignedDEC > 90.0 || alignedDEC < -90.0)
459 if (alignedDEC > 0.0)
460 alignedDEC = 180.0 - alignedDEC;
462 alignedDEC = -180.0 - alignedDEC;
464 alignedRA =
range24(alignedRA);
477 sendCommand(
cmd,
nullptr);
497 LOG_DEBUG(
"Sending LST --> Z --> LST before Sync.");
510 snprintf(
cmd,
TEMMA_BUFFER,
"D%.2d%.2d%.2d%c%.2d%.2d%.1d", (
int)
ra, (
int)(
ra * (
double)60) % 60,
511 ((
int)(
ra * (
double)6000)) % 100, sign, (
int)
dec, (
int)(
dec * (
double)60) % 60,
512 ((
int)(
dec * (
double)600)) % 10);
514 if (sendCommand(
cmd, res) ==
false)
545 if (MotorStatus ==
false)
548 setMotorsEnabled(
true);
561 snprintf(
cmd,
TEMMA_BUFFER,
"P%.2d%.2d%.2d%c%.2d%.2d%.1d", (
int)
ra, (
int)(
ra * (
double)60) % 60,
562 ((
int)(
ra * (
double)6000)) % 100, sign, (
int)
dec, (
int)(
dec * (
double)60) % 60,
563 ((
int)(
dec * (
double)600)) % 10);
565 if (sendCommand(
cmd, res) ==
false)
580 TrackState = SCOPE_SLEWING;
591 SetAxis1Park(
range24(lst + 3 / 60.0));
592 LOGF_DEBUG(
"heading to Park position %4.2f %4.2f", GetAxis1Park(), GetAxis2Park());
594 Goto(GetAxis1Park(), GetAxis2Park());
596 TrackState = SCOPE_PARKING;
597 LOG_INFO(
"Parking is in progress...");
608 LOGF_INFO(
"Syncing to Park position %4.2f %4.2f", GetAxis1Park(), GetAxis2Park());
609 Sync(GetAxis1Park(), GetAxis2Park());
613 setMotorsEnabled(
true);
615 TrackState = SCOPE_TRACKING;
617 TrackState = SCOPE_IDLE;
632 SetAxis1Park(
range24(lst + 3 / 60.0));
633 SetAxis2Park(Latitude >= 0 ? 90 : -90);
642 if (sendCommand(
"PS") ==
false)
645 if (sendCommand(
"s", res) ==
false)
655 LOGF_DEBUG(
"Temma::MoveNS %d dir %d", command, dir);
657 setMotorsEnabled(
true);
664 LOGF_DEBUG(
"Temma::MoveNS %d dir %d", command, dir);
665 if (command == MOTION_START)
694 return sendCommand(
cmd);
702 setMotorsEnabled(
true);
709 LOGF_DEBUG(
"Temma::MoveWE %d dir %d", command, dir);
710 if (command == MOTION_START)
736 return sendCommand(
cmd);
862 Longitude = longitude;
869 if (TemmaInitialized ==
false)
871 setLatitude(latitude);
874 TemmaInitialized =
true;
878 LOGF_DEBUG(
"Temma is initialized. Latitude: %.2f LST: %.2f", latitude, lst);
881 LOGF_INFO(
"Syncing to default home position %4.2f %4.2f", GetAxis1Park(), GetAxis2Park());
882 Sync(GetAxis1Park(), GetAxis2Park());
898 LOGF_INFO(
"Syncing to Park position %4.2f %4.2f", GetAxis1Park(), GetAxis2Park());
899 Sync(GetAxis1Park(), GetAxis2Park());
901 setMotorsEnabled(
false);
917 double RightAscension, Declination;
920 if (GetAlignmentDatabase().size() > 1)
949 lha = lha * 360 / 24;
952 TDV = TelescopeDirectionVectorFromLocalHourAngleDeclination(
eq);
954 if (TransformTelescopeToCelestial(TDV, RightAscension, Declination))
974 eq.ra = RightAscension;
975 eq.dec = Declination;
983 double RightAscension, Declination;
988 if (GetAlignmentDatabase().size() > 1)
993 if (TransformCelestialToTelescope(
ra,
dec, 0.0, TDV))
1019 LocalHourAngleDeclinationFromTelescopeDirectionVector(TDV,
eq);
1022 eq.ra =
eq.ra * 24 / 360;
1023 RightAscension = lst -
eq.ra;
1024 RightAscension =
range24(RightAscension);
1025 Declination =
eq.dec;
1029 LOGF_INFO(
"Transform failed, using raw co-ordinates %g %g",
ra,
dec);
1030 RightAscension =
ra;
1036 RightAscension =
ra;
1040 eq.ra = RightAscension;
1041 eq.dec = Declination;
1048 bool TemmaMount::getVersion()
1051 for (
int i = 0; i < 3; i++)
1053 if (sendCommand(
"v", res) && res[0] ==
'v')
1065 LOGF_INFO(
"Detected version: %s", res + 1);
1070 bool TemmaMount::motorsEnabled()
1074 if (sendCommand(
"STN-COD", res) ==
false)
1077 if (strstr(res,
"off") !=
nullptr)
1080 MotorStatus =
false;
1087 bool TemmaMount::setMotorsEnabled(
bool enable)
1095 rc = sendCommand(
"STN-OFF", res);
1097 rc = sendCommand(
"STN-ON", res);
1108 bool TemmaMount::getLST(
double &lst)
1112 if (sendCommand(
"g", res) ==
false)
1115 int hh = 0, mm = 0, ss = 0;
1116 if (sscanf(res + 1,
"%02d%02d%02d", &hh, &mm, &ss) == 3)
1118 lst = hh + mm / 60.0 + ss / 3600.0;
1125 bool TemmaMount::setLST()
1129 snprintf(
cmd,
TEMMA_BUFFER,
"T%.2d%.2d%.2d", (
int)lst, ((
int)(lst * 60)) % 60, ((
int)(lst * 3600)) % 60);
1131 return sendCommand(
cmd);
1134 bool TemmaMount::getLatitude(
double &lat)
1138 if (sendCommand(
"i", res) ==
false)
1141 int dd = 0, mm = 0, parial_m = 0;
1142 if (sscanf(res + 1,
"%02d%02d%01d", &dd, &mm, &parial_m) == 3)
1144 lat = dd + mm / 60.0 + parial_m / 600.0;
1151 bool TemmaMount::setLatitude(
double lat)
1175 return sendCommand(
cmd);
1196 TemmaInitialized =
true;
1201 TemmaInitialized =
false;
1210 int TemmaMount::TemmaRead(
char *buf,
int size)
1219 rc =
tty_read(PortFD, &buf[ptr], 1, 2,
1230 if (buf[ptr - 1] == 13)
1242 fprintf(stderr,
"timed out reading %d\n", count);
1243 LOGF_DEBUG(
"We timed out reading bytes %d", count);
1248 fprintf(stderr,
"Read error after %d bytes\n", bytesRead);
1249 LOGF_DEBUG(
"Read return error after %d bytes", bytesRead);
1256 if (mode == TRACK_SIDEREAL)
1257 return sendCommand(
"LL");
1258 else if (mode == TRACK_SOLAR)
1259 return sendCommand(
"LK");
1268 setMotorsEnabled(
true);
1273 setMotorsEnabled(
false);
1274 return sendCommand(
"PS");
1278 void TemmaMount::mountSim()
1280 static struct timeval ltv;
1282 double dt = 0, da = 0, dx = 0;
1286 gettimeofday(&tv,
nullptr);
1288 if (ltv.tv_sec == 0 && ltv.tv_usec == 0)
1291 dt = tv.tv_sec - ltv.tv_sec + (tv.tv_usec - ltv.tv_usec) / 1e6;
1303 case SCOPE_TRACKING:
1306 case TRACK_SIDEREAL:
1323 dx = (TrackRateN[
AXIS_DE].value / 3600.0 * dt);
1362 if (TrackState == SCOPE_SLEWING)
1363 TrackState = SCOPE_TRACKING;
virtual bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
Process the client newBLOB command.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual bool SetSlewRate(int index)
SetSlewRate Set desired slew rate index.
virtual void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual bool updateTime(ln_date *utc, double utc_offset)
Update telescope time, date, and UTC offset.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool ReadScopeStatus() override
Read telescope status.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n) override
Process the client newBLOB command.
virtual bool Handshake() override
perform handshake with device to check communication
virtual bool Sync(double ra, double dec) override
Set the telescope current RA and DEC coordinates to the supplied RA and DEC coordinates.
virtual const char * getDefaultName() override
virtual bool SetDefaultPark() override
SetDefaultPark Set default coordinates/encoders value as the desired parking position.
virtual IPState GuideWest(uint32_t ms) override
Guide west for ms milliseconds. West is defined as RA-.
virtual IPState GuideSouth(uint32_t ms) override
Guide south for ms milliseconds. South is defined as DEC-.
virtual bool Goto(double ra, double dec) override
Move the scope to the supplied RA and DEC coordinates.
virtual bool initProperties() override
Called to initialize basic properties required all the time.
virtual bool UnPark() override
Unpark the telescope if already parked.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
virtual bool SetTrackEnabled(bool enabled) override
SetTrackEnabled Engages or disengages mount tracking. If there are no tracking modes available,...
virtual bool MoveWE(INDI_DIR_WE dir, TelescopeMotionCommand command) override
Move the telescope in the direction dir.
virtual bool Abort() override
Abort any telescope motion including tracking if possible.
virtual bool Park() override
Park the telescope to its home position.
virtual bool MoveNS(INDI_DIR_NS dir, TelescopeMotionCommand command) override
Start or Stop the telescope motion in the direction dir.
virtual bool SetCurrentPark() override
SetCurrentPark Set current coordinates/encoders value as the desired parking position.
virtual IPState GuideEast(uint32_t ms) override
Guide east for ms milliseconds. East is defined as RA+.
virtual bool updateProperties() override
Called when connected state changes, to add/remove properties.
virtual bool SetTrackMode(uint8_t mode) override
SetTrackMode Set active tracking mode. Do not change track state.
virtual IPState GuideNorth(uint32_t ms) override
Guide north for ms milliseconds. North is defined as DEC+.
virtual bool updateLocation(double latitude, double longitude, double elevation) override
Update telescope location settings.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
const char * MOTION_TAB
MOTION_TAB Where all the motion control properties of the device are located.
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
double range24(double r)
range24 Limits a number to be between 0-24 range.
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
int tty_nread_section(int fd, char *buf, int nsize, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
double get_local_hour_angle(double sideral_time, double ra)
get_local_hour_angle Returns local hour angle of an object
Implementations for common driver routines.
double get_local_sidereal_time(double longitude)
get_local_sidereal_time Returns local sideral time given longitude and system clock.
#define TRACKRATE_SIDEREAL
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
#define LOGF_INFO(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
#define DEBUGF(priority, msg,...)
int Sync(int fd, char *matchedObject)
Namespace to encapsulate the INDI Alignment Subsystem classes. For more information see "INDI Alignme...
bool getVersion(const int fd, char response[])
const char * getDeviceName()
bool isParked(const int fd)
@ binary
binary array (ordered collection of bytes)
Holds a nomalised direction vector (direction cosines)