36 static std::unique_ptr<DeepSkyDadAF1> deepSkyDadAf1(
new DeepSkyDadAF1());
52 IUFillSwitchVector(&StepModeSP, StepModeS, 4,
getDeviceName(),
"Step Mode",
"",
OPTIONS_TAB,
IP_RW,
ISR_1OFMANY, 0,
67 IUFillNumber(&FocusMaxMoveN[0],
"MAX_MOVE",
"Steps",
"%7.0f", 0, 9999999, 100, 0);
72 IUFillNumber(&SettleBufferN[0],
"SETTLE_BUFFER",
"Period (ms)",
"%5.0f", 0, 99999, 100, 0);
77 IUFillNumber(&IdleCoilsTimeoutN[0],
"IDLE_COILS_TIMEOUT",
"Period (ms)",
"%6.0f", 0, 999999, 1000, 60000);
79 "Idle - coils timeout",
86 IUFillSwitchVector(&CoilsModeSP, CoilsModeS, 3,
getDeviceName(),
"Coils mode",
"",
OPTIONS_TAB,
IP_RW,
ISR_1OFMANY, 0,
127 LOG_INFO(
"deepSkyDadAf1 parameters updated, focuser ready for use.");
147 LOG_INFO(
"deepSkyDadAf1 is online. Getting focus parameters...");
152 "Error retrieving data from deepSkyDadAf1, please ensure deepSkyDadAf1 controller is powered and the port is correct.");
158 return "Deep Sky Dad AF1";
161 bool DeepSkyDadAF1::Ack()
165 char res[DSD_RES] = {0};
166 if (!sendCommand(
"[GPOS]", res))
173 int rc = sscanf(res,
"(%d)", &pos);
184 bool DeepSkyDadAF1::readStepMode()
186 char res[DSD_RES] = {0};
188 if (sendCommand(
"[GSTP]", res) ==
false)
191 if (strcmp(res,
"(1)") == 0)
193 else if (strcmp(res,
"(2)") == 0)
195 else if (strcmp(res,
"(4)") == 0)
197 else if (strcmp(res,
"(8)") == 0)
201 LOGF_ERROR(
"Unknown error: focuser step value (%s)", res);
208 bool DeepSkyDadAF1::readPosition()
210 char res[DSD_RES] = {0};
212 if (sendCommand(
"[GPOS]", res) ==
false)
216 int rc = sscanf(res,
"(%d)", &pos);
222 LOGF_ERROR(
"Unknown error: focuser position value (%s)", res);
229 bool DeepSkyDadAF1::readMaxMovement()
231 char res[DSD_RES] = {0};
233 if (sendCommand(
"[GMXM]", res) ==
false)
237 int rc = sscanf(res,
"(%d)", &steps);
240 FocusMaxMoveN[0].value = steps;
245 LOGF_ERROR(
"Unknown error: maximum movement value (%s)", res);
252 bool DeepSkyDadAF1::readMaxPosition()
254 char res[DSD_RES] = {0};
256 if (sendCommand(
"[GMXP]", res) ==
false)
260 int rc = sscanf(res,
"(%d)", &steps);
268 LOGF_ERROR(
"Unknown error: maximum position value (%s)", res);
275 bool DeepSkyDadAF1::readSettleBuffer()
277 char res[DSD_RES] = {0};
279 if (sendCommand(
"[GBUF]", res) ==
false)
282 uint32_t settleBuffer = 0;
283 int rc = sscanf(res,
"(%d)", &settleBuffer);
286 SettleBufferN[0].value = settleBuffer;
291 LOGF_ERROR(
"Unknown error: settle buffer value (%s)", res);
298 bool DeepSkyDadAF1::readIdleCoilsTimeout()
300 char res[DSD_RES] = {0};
302 if (sendCommand(
"[GIDC]", res) ==
false)
306 int rc = sscanf(res,
"(%d)", &ms);
309 IdleCoilsTimeoutN[0].value = ms;
314 LOGF_ERROR(
"Unknown error: idle coils timeout value (%s)", res);
321 bool DeepSkyDadAF1::readCoilsMode()
323 char res[DSD_RES] = {0};
325 if (sendCommand(
"[GCLM]", res) ==
false)
328 if (strcmp(res,
"(0)") == 0)
333 else if (strcmp(res,
"(1)") == 0)
338 else if (strcmp(res,
"(2)") == 0)
345 LOGF_ERROR(
"Unknown error: readCoilsMode value (%s)", res);
352 bool DeepSkyDadAF1::readCurrentMove()
354 char res[DSD_RES] = {0};
356 if (sendCommand(
"[GCMV%]", res) ==
false)
359 if (strcmp(res,
"(25%)") == 0)
364 else if (strcmp(res,
"(50%)") == 0)
369 else if (strcmp(res,
"(75%)") == 0)
374 else if (strcmp(res,
"(100%)") == 0)
382 LOGF_ERROR(
"Unknown error: currentMove value (%s)", res);
389 bool DeepSkyDadAF1::readCurrentHold()
391 char res[DSD_RES] = {0};
393 if (sendCommand(
"[GCHD%]", res) ==
false)
396 if (strcmp(res,
"(25%)") == 0)
401 else if (strcmp(res,
"(50%)") == 0)
406 else if (strcmp(res,
"(75%)") == 0)
411 else if (strcmp(res,
"(100%)") == 0)
419 LOGF_ERROR(
"Unknown error: currentMove value (%s)", res);
426 bool DeepSkyDadAF1::isMoving()
428 char res[DSD_RES] = {0};
430 if (sendCommand(
"[GMOV]", res) ==
false)
433 if (strcmp(res,
"(1)") == 0)
435 else if (strcmp(res,
"(0)") == 0)
438 LOGF_ERROR(
"Unknown error: isMoving value (%s)", res);
444 char cmd[DSD_RES] = {0};
445 snprintf(
cmd, DSD_RES,
"[SPOS%06d]", ticks);
446 return sendCommand(
cmd);
451 char cmd[DSD_RES] = {0};
452 snprintf(
cmd, DSD_RES,
"[SREV%01d]", enabled ? 1 : 0);
453 return sendCommand(
cmd);
458 char cmd[DSD_RES] = {0};
459 char res[DSD_RES] = {0};
460 snprintf(
cmd, DSD_RES,
"[STRG%06d]", position);
462 if (sendCommand(
cmd, res) ==
false)
465 if(strcmp(res,
"!101)") == 0)
467 LOG_ERROR(
"MoveFocuserFailed - requested movement too big. You can increase the limit by changing the value of Max. movement.");
472 if (sendCommand(
"[SMOV]") ==
false)
483 if (strcmp(StepModeSP.
name, name) == 0)
491 if (current_mode == target_mode)
498 char cmd[DSD_RES] = {0};
502 else if(target_mode == 1)
504 else if(target_mode == 2)
506 else if(target_mode == 3)
509 snprintf(
cmd, DSD_RES,
"[SSTP%d]", target_mode);
510 bool rc = sendCommandSet(
cmd);
514 StepModeS[current_mode].s =
ISS_ON;
526 if (strcmp(CoilsModeSP.
name, name) == 0)
534 if (coilsModeCurrent == coilsModeTarget)
540 if(coilsModeTarget == 0)
542 else if(coilsModeTarget == 1)
544 else if(coilsModeTarget == 2)
547 char cmd[DSD_RES] = {0};
548 snprintf(
cmd, DSD_RES,
"[SCLM%d]", coilsModeTarget);
550 bool rc = sendCommandSet(
cmd);
554 CoilsModeS[coilsModeCurrent].s =
ISS_ON;
566 if (strcmp(CurrentMoveSP.
name, name) == 0)
574 if (current == targetCurrent)
580 int targetCurrentValue = 75;
581 switch(targetCurrent)
584 targetCurrentValue = 25;
587 targetCurrentValue = 50;
590 targetCurrentValue = 75;
593 targetCurrentValue = 100;
597 char cmd[DSD_RES] = {0};
598 snprintf(
cmd, DSD_RES,
"[SCMV%d%%]", targetCurrentValue);
600 bool rc = sendCommandSet(
cmd);
604 CurrentMoveS[current].s =
ISS_ON;
616 if (strcmp(CurrentHoldSP.
name, name) == 0)
624 if (current == targetCurrent)
630 int targetCurrentValue = 75;
631 switch(targetCurrent)
634 targetCurrentValue = 25;
637 targetCurrentValue = 50;
640 targetCurrentValue = 75;
643 targetCurrentValue = 100;
647 char cmd[DSD_RES] = {0};
648 snprintf(
cmd, DSD_RES,
"[SCHD%d%%]", targetCurrentValue);
650 bool rc = sendCommandSet(
cmd);
654 CurrentHoldS[current].s =
ISS_ON;
674 if (strcmp(name, SettleBufferNP.
name) == 0)
677 char cmd[DSD_RES] = {0};
678 snprintf(
cmd, DSD_RES,
"[SBUF%06d]",
static_cast<int>(SettleBufferN[0].value));
679 bool rc = sendCommandSet(
cmd);
692 if (strcmp(name, IdleCoilsTimeoutNP.
name) == 0)
695 char cmd[DSD_RES] = {0};
696 snprintf(
cmd, DSD_RES,
"[SIDC%06d]",
static_cast<int>(IdleCoilsTimeoutN[0].value));
697 bool rc = sendCommandSet(
cmd);
713 char cmd[DSD_RES] = {0};
714 snprintf(
cmd, DSD_RES,
"[SMXP%d]",
static_cast<int>(
FocusMaxPosN[0].value));
715 bool rc = sendCommandSet(
cmd);
728 if (strcmp(name, FocusMaxMoveNP.
name) == 0)
731 char cmd[DSD_RES] = {0};
732 snprintf(
cmd, DSD_RES,
"[SMXM%d]",
static_cast<int>(FocusMaxMoveN[0].value));
733 bool rc = sendCommandSet(
cmd);
749 void DeepSkyDadAF1::GetFocusParams()
762 if (readSettleBuffer())
765 if (readMaxPosition())
768 if (readMaxMovement())
771 if (readIdleCoilsTimeout())
777 if (readCurrentMove())
780 if (readCurrentHold())
803 void DeepSkyDadAF1::timedMoveCallback()
818 targetPos = targetTicks;
828 int32_t newPosition = 0;
855 bool rc = readPosition();
874 LOG_INFO(
"Focuser reached requested position.");
883 return sendCommand(
"[STOP]");
888 Focuser::saveConfigItems(fp);
901 bool DeepSkyDadAF1::sendCommand(
const char *
cmd,
char * res)
903 int nbytes_written = 0, nbytes_read = 0, rc = -1;
905 tcflush(
PortFD, TCIOFLUSH);
913 LOGF_ERROR(
"Serial write error: %s.", errstr);
930 tcflush(
PortFD, TCIOFLUSH);
935 bool DeepSkyDadAF1::sendCommandSet(
const char *
cmd)
937 char res[DSD_RES] = {0};
939 if (sendCommand(
cmd, res) ==
false)
942 return strcmp(res,
"(OK)") == 0;
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
static void timedMoveHelper(void *context)
const char * getDefaultName() override
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveAbsFocuser Move to an absolute target position.
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool Handshake() override
perform handshake with device to check communication
virtual bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
virtual IPState MoveFocuser(FocusDirection dir, int speed, uint16_t duration) override
MoveFocuser Move focuser in a specific direction and speed for period of time.
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveRelFocuser Move focuser for a relative amount of ticks in a specific direction.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set current position to ticks without moving the focuser.
const char * getDeviceName() const
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void addDebugControl()
Add Debug control to the driver.
INumberVectorProperty FocusAbsPosNP
INumberVectorProperty FocusRelPosNP
INumberVectorProperty FocusTimerNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INumberVectorProperty FocusMaxPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
int IEAddTimer(int millisecs, IE_TCF *fp, void *p)
Register a new single-shot timer function, fp, to be called with ud as argument after ms.
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
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
Implementations for common driver routines.
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
void IUFillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a number vector property. The vector's auxiliary elements will be set to NULL.
int IUFindOnSwitchIndex(const ISwitchVectorProperty *svp)
Returns the index of first ON switch it finds in the vector switch property.
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
void IUFillNumber(INumber *np, const char *name, const char *label, const char *format, double min, double max, double step, double value)
Assign attributes for a number property. The number's auxiliary elements will be set to NULL.
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
#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,...)