36static std::unique_ptr<DeepSkyDadAF3> deepSkyDadAf3(
new DeepSkyDadAF3());
97 SettleBufferNP[0].
fill(
"SETTLE_BUFFER",
"Period (ms)",
"%5.0f", 0, 99999, 100, 0);
102 MoveCurrentMultiplierNP[0].
fill(
"MOTOR_MOVE_MULTIPLIER",
"%",
"%3.0f", 1, 100, 1, 90);
104 "Move current multiplier",
108 HoldCurrentMultiplierNP[0].
fill(
"MOTOR_HOLD_MULTIPLIER",
"%",
"%3.0f", 1, 100, 1, 40);
110 "Hold current multiplier",
114 TemperatureNP[0].
fill(
"TEMPERATURE",
"Celsius",
"%6.2f", -50, 70., 0., 0.);
139 LOG_INFO(
"deepSkyDadAf3 parameters updated, focuser ready for use.");
158 LOG_INFO(
"deepSkyDadAf3 is online. Getting focus parameters...");
163 "Error retrieving data from deepSkyDadAf3, please ensure deepSkyDadAf3 controller is powered and the port is correct.");
169 return "Deep Sky Dad AF3";
172bool DeepSkyDadAF3::Ack()
176 char res[DSD_RES] = {0};
177 if (!sendCommand(
"[GPOS]", res) && !sendCommand(
"[GPOS]", res))
184 int rc = sscanf(res,
"(%d)", &pos);
195bool DeepSkyDadAF3::readStepMode()
197 char res[DSD_RES] = {0};
199 if (sendCommand(
"[GSTP]", res) ==
false)
202 if (strcmp(res,
"(1)") == 0)
204 else if (strcmp(res,
"(2)") == 0)
206 else if (strcmp(res,
"(4)") == 0)
208 else if (strcmp(res,
"(8)") == 0)
210 else if (strcmp(res,
"(16)") == 0)
212 else if (strcmp(res,
"(32)") == 0)
214 else if (strcmp(res,
"(64)") == 0)
216 else if (strcmp(res,
"(128)") == 0)
218 else if (strcmp(res,
"(256)") == 0)
222 LOGF_ERROR(
"Unknown error: focuser step value (%s)", res);
230bool DeepSkyDadAF3::readSpeedMode()
232 char res[DSD_RES] = {0};
234 if (sendCommand(
"[GSPD]", res) ==
false)
237 if (strcmp(res,
"(1)") == 0)
239 else if (strcmp(res,
"(2)") == 0)
241 else if (strcmp(res,
"(3)") == 0)
243 else if (strcmp(res,
"(4)") == 0)
245 else if (strcmp(res,
"(5)") == 0)
249 LOGF_ERROR(
"Unknown error: focuser speed value (%s)", res);
257bool DeepSkyDadAF3::readPosition()
259 char res[DSD_RES] = {0};
261 if (sendCommand(
"[GPOS]", res) ==
false)
265 int rc = sscanf(res,
"(%d)", &pos);
271 LOGF_ERROR(
"Unknown error: focuser position value (%s)", res);
278bool DeepSkyDadAF3::readMaxMovement()
280 char res[DSD_RES] = {0};
282 if (sendCommand(
"[GMXM]", res) ==
false)
286 int rc = sscanf(res,
"(%d)", &steps);
294 LOGF_ERROR(
"Unknown error: maximum movement value (%s)", res);
301bool DeepSkyDadAF3::readMaxPosition()
303 char res[DSD_RES] = {0};
305 if (sendCommand(
"[GMXP]", res) ==
false)
309 int rc = sscanf(res,
"(%d)", &steps);
317 LOGF_ERROR(
"Unknown error: maximum position value (%s)", res);
324bool DeepSkyDadAF3::readSettleBuffer()
326 char res[DSD_RES] = {0};
328 if (sendCommand(
"[GBUF]", res) ==
false)
331 uint32_t settleBuffer = 0;
332 int rc = sscanf(res,
"(%d)", &settleBuffer);
335 SettleBufferNP[0].setValue(settleBuffer);
340 LOGF_ERROR(
"Unknown error: settle buffer value (%s)", res);
347bool DeepSkyDadAF3::readMoveCurrentMultiplier()
349 char res[DSD_RES] = {0};
351 if (sendCommand(
"[GMMM]", res) ==
false)
355 int rc = sscanf(res,
"(%d)", &mcm);
358 MoveCurrentMultiplierNP[0].setValue(mcm);
363 LOGF_ERROR(
"Unknown error: move current multiplier value (%s)", res);
370bool DeepSkyDadAF3::readHoldCurrentMultiplier()
372 char res[DSD_RES] = {0};
374 if (sendCommand(
"[GMHM]", res) ==
false)
378 int rc = sscanf(res,
"(%d)", &hcm);
381 HoldCurrentMultiplierNP[0].setValue(hcm);
386 LOGF_ERROR(
"Unknown error: hold current multiplier value (%s)", res);
393bool DeepSkyDadAF3::readTemperature()
395 char res[DSD_RES] = {0};
397 if (sendCommand(
"[GTMC]", res) ==
false)
401 int rc = sscanf(res,
"(%lf)", &temp);
404 TemperatureNP[0].setValue(temp);
408 LOGF_ERROR(
"Unknown error: focuser temperature value (%s)", res);
415bool DeepSkyDadAF3::isMoving()
417 char res[DSD_RES] = {0};
419 if (sendCommand(
"[GMOV]", res) ==
false)
422 if (strcmp(res,
"(1)") == 0)
424 else if (strcmp(res,
"(0)") == 0)
427 LOGF_ERROR(
"Unknown error: isMoving value (%s)", res);
433 char cmd[DSD_RES] = {0};
434 snprintf(
cmd, DSD_RES,
"[SPOS%07d]", ticks);
435 char res[DSD_RES] = {0};
436 return sendCommand(
cmd, res);
441 char cmd[DSD_RES] = {0};
442 snprintf(
cmd, DSD_RES,
"[SREV%01d]", enabled ? 1 : 0);
443 char res[DSD_RES] = {0};
444 return sendCommand(
cmd, res);
449 char cmd[DSD_RES] = {0};
450 char res[DSD_RES] = {0};
451 snprintf(
cmd, DSD_RES,
"[STRG%06d]", position);
453 if (sendCommand(
cmd, res) ==
false)
456 if(strcmp(res,
"!101)") == 0)
458 LOG_ERROR(
"MoveFocuserFailed - requested movement too big. You can increase the limit by changing the value of Max. movement.");
463 if (sendCommand(
"[SMOV]", res) ==
false)
478 StepModeSP.
update(states, names, n);
482 if (current_mode == target_mode)
489 char cmd[DSD_RES] = {0};
493 else if(target_mode == 1)
495 else if(target_mode == 2)
497 else if(target_mode == 3)
499 else if(target_mode == 4)
501 else if(target_mode == 5)
503 else if(target_mode == 6)
505 else if(target_mode == 7)
507 else if(target_mode == 8)
510 snprintf(
cmd, DSD_RES,
"[SSTP%d]", target_mode);
511 bool rc = sendCommandSet(
cmd);
531 SpeedModeSP.
update(states, names, n);
535 if (current_mode == target_mode)
542 char cmd[DSD_RES] = {0};
546 else if(target_mode == 1)
548 else if(target_mode == 2)
550 else if(target_mode == 3)
552 else if(target_mode == 4)
555 snprintf(
cmd, DSD_RES,
"[SSPD%d]", target_mode);
556 bool rc = sendCommandSet(
cmd);
582 SettleBufferNP.
update(values, names, n);
583 char cmd[DSD_RES] = {0};
584 snprintf(
cmd, DSD_RES,
"[SBUF%06d]",
static_cast<int>(SettleBufferNP[0].getValue()));
585 bool rc = sendCommandSet(
cmd);
593 SettleBufferNP.
apply();
600 MoveCurrentMultiplierNP.
update(values, names, n);
601 char cmd[DSD_RES] = {0};
602 snprintf(
cmd, DSD_RES,
"[SMMM%03d]",
static_cast<int>(MoveCurrentMultiplierNP[0].getValue()));
603 bool rc = sendCommandSet(
cmd);
611 MoveCurrentMultiplierNP.
apply();
618 HoldCurrentMultiplierNP.
update(values, names, n);
619 char cmd[DSD_RES] = {0};
620 snprintf(
cmd, DSD_RES,
"[SMHM%03d]",
static_cast<int>(HoldCurrentMultiplierNP[0].getValue()));
621 bool rc = sendCommandSet(
cmd);
629 HoldCurrentMultiplierNP.
apply();
637void DeepSkyDadAF3::GetFocusParams()
651 if (readSettleBuffer())
652 SettleBufferNP.
apply();
654 if (readMoveCurrentMultiplier())
655 MoveCurrentMultiplierNP.
apply();
657 if (readHoldCurrentMultiplier())
658 HoldCurrentMultiplierNP.
apply();
660 if (readMaxPosition())
663 if (readMaxMovement())
666 if (readTemperature())
667 TemperatureNP.
apply();
689void DeepSkyDadAF3::timedMoveCallback()
704 targetPos = targetTicks;
708 if ((diff > 0 && bcValue < 0) || (diff < 0 && bcValue > 0))
710 backlashComp = bcValue;
711 targetPos -= bcValue;
722 int32_t newPosition = 0;
730 newPosition = std::max(0, std::min(
static_cast<int32_t
>(
FocusAbsPosNP[0].getMax()), newPosition));
749 bool rc = readPosition();
763 if( backlashComp == 0 )
776 else if(backlashComp != 0)
778 LOGF_INFO(
"Performing backlash compensation of %i.", (
int)backlashComp);
779 targetPos += backlashComp;
784 LOG_INFO(
"Focuser reached requested position.");
792 rc = readTemperature();
796 if (std::abs(lastTemperature - TemperatureNP[0].getValue()) >= 0.1)
798 TemperatureNP.
apply();
799 lastTemperature = TemperatureNP[0].getValue();
809 return sendCommand(
"[STOP]");
814 Focuser::saveConfigItems(fp);
817 SpeedModeSP.
save(fp);
818 SettleBufferNP.
save(fp);
819 MoveCurrentMultiplierNP.
save(fp);
820 HoldCurrentMultiplierNP.
save(fp);
825bool DeepSkyDadAF3::sendCommand(
const char *
cmd,
char * res)
827 int nbytes_written = 0, nbytes_read = 0, rc = -1;
829 tcflush(
PortFD, TCIOFLUSH);
837 LOGF_ERROR(
"Serial write error: %s.", errstr);
854 tcflush(
PortFD, TCIOFLUSH);
859bool DeepSkyDadAF3::sendCommandSet(
const char *
cmd)
861 char res[DSD_RES] = {0};
863 if (sendCommand(
cmd, res) ==
false)
866 return strcmp(res,
"(OK)") == 0;
877 char cmd[DSD_RES] = {0};
879 snprintf(
cmd, DSD_RES,
"[SMXP%d]", ticks);
881 if (sendCommandSet(
cmd))
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
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool SetFocuserMaxPosition(uint32_t ticks) override
SetFocuserMaxPosition Update focuser maximum position. It only updates the PresetNP property limits.
virtual bool SyncFocuser(uint32_t ticks) override
SyncFocuser Set current position to ticks without moving the focuser.
virtual bool Handshake() override
Performs a device-specific handshake after a connection is established. This method should be overrid...
static void timedMoveHelper(void *context)
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 bool ReverseFocuser(bool enabled) override
ReverseFocuser Reverse focuser motion direction.
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
const char * getDefaultName() override
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveAbsFocuser Move to an absolute target position.
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.
INDI::PropertyNumber FocusRelPosNP
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
INDI::PropertyNumber FocusSyncNP
INDI::PropertyNumber FocusTimerNP
INDI::PropertyNumber FocusMaxPosNP
INDI::PropertyNumber FocusBacklashNP
INDI::PropertyNumber FocusAbsPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Processes incoming new switch states from the client for this device. Handles updates to FocuserInter...
virtual bool updateProperties() override
Updates the state and definition of properties based on the current connection status....
virtual bool initProperties() override
Initializes the default properties for the focuser device. Sets up standard INDI properties,...
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Processes incoming new number values from the client for this device. Handles updates to FocuserInter...
virtual void SyncPresets(uint32_t ticks)
Synchronizes the range (min, max, step) of the preset number properties (PresetNP) based on the focus...
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
bool isNameMatch(const char *otherName) const
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool update(const ISState states[], const char *const names[], int n)
int findOnSwitchIndex() const
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
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.
#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,...)