36 static std::unique_ptr<DeepSkyDadAF3> deepSkyDadAf3(
new DeepSkyDadAF3());
58 IUFillSwitchVector(&StepModeSP, StepModeS, 9,
getDeviceName(),
"Step Mode",
"",
OPTIONS_TAB,
IP_RW,
ISR_1OFMANY, 0,
67 IUFillSwitchVector(&SpeedModeSP, SpeedModeS, 5,
getDeviceName(),
"Speed Mode",
"",
OPTIONS_TAB,
IP_RW,
ISR_1OFMANY, 0,
97 IUFillNumber(&FocusMaxMoveN[0],
"MAX_MOVE",
"Steps",
"%7.0f", 0, 9999999, 100, 0);
102 IUFillNumber(&SettleBufferN[0],
"SETTLE_BUFFER",
"Period (ms)",
"%5.0f", 0, 99999, 100, 0);
107 IUFillNumber(&MoveCurrentMultiplierN[0],
"MOTOR_MOVE_MULTIPLIER",
"%",
"%3.0f", 1, 100, 1, 90);
109 "Move current multiplier",
113 IUFillNumber(&HoldCurrentMultiplierN[0],
"MOTOR_HOLD_MULTIPLIER",
"%",
"%3.0f", 1, 100, 1, 40);
115 "Hold current multiplier",
119 IUFillNumber(&TemperatureN[0],
"TEMPERATURE",
"Celsius",
"%6.2f", -50, 70., 0., 0.);
145 LOG_INFO(
"deepSkyDadAf3 parameters updated, focuser ready for use.");
165 LOG_INFO(
"deepSkyDadAf3 is online. Getting focus parameters...");
170 "Error retrieving data from deepSkyDadAf3, please ensure deepSkyDadAf3 controller is powered and the port is correct.");
176 return "Deep Sky Dad AF3";
179 bool DeepSkyDadAF3::Ack()
183 char res[DSD_RES] = {0};
184 if (!sendCommand(
"[GPOS]", res) && !sendCommand(
"[GPOS]", res))
191 int rc = sscanf(res,
"(%d)", &pos);
202 bool DeepSkyDadAF3::readStepMode()
204 char res[DSD_RES] = {0};
206 if (sendCommand(
"[GSTP]", res) ==
false)
209 if (strcmp(res,
"(1)") == 0)
211 else if (strcmp(res,
"(2)") == 0)
213 else if (strcmp(res,
"(4)") == 0)
215 else if (strcmp(res,
"(8)") == 0)
217 else if (strcmp(res,
"(16)") == 0)
219 else if (strcmp(res,
"(32)") == 0)
221 else if (strcmp(res,
"(64)") == 0)
223 else if (strcmp(res,
"(128)") == 0)
225 else if (strcmp(res,
"(256)") == 0)
229 LOGF_ERROR(
"Unknown error: focuser step value (%s)", res);
237 bool DeepSkyDadAF3::readSpeedMode()
239 char res[DSD_RES] = {0};
241 if (sendCommand(
"[GSPD]", res) ==
false)
244 if (strcmp(res,
"(1)") == 0)
246 else if (strcmp(res,
"(2)") == 0)
248 else if (strcmp(res,
"(3)") == 0)
250 else if (strcmp(res,
"(4)") == 0)
252 else if (strcmp(res,
"(5)") == 0)
256 LOGF_ERROR(
"Unknown error: focuser speed value (%s)", res);
264 bool DeepSkyDadAF3::readPosition()
266 char res[DSD_RES] = {0};
268 if (sendCommand(
"[GPOS]", res) ==
false)
272 int rc = sscanf(res,
"(%d)", &pos);
278 LOGF_ERROR(
"Unknown error: focuser position value (%s)", res);
285 bool DeepSkyDadAF3::readMaxMovement()
287 char res[DSD_RES] = {0};
289 if (sendCommand(
"[GMXM]", res) ==
false)
293 int rc = sscanf(res,
"(%d)", &steps);
296 FocusMaxMoveN[0].value = steps;
301 LOGF_ERROR(
"Unknown error: maximum movement value (%s)", res);
308 bool DeepSkyDadAF3::readMaxPosition()
310 char res[DSD_RES] = {0};
312 if (sendCommand(
"[GMXP]", res) ==
false)
316 int rc = sscanf(res,
"(%d)", &steps);
324 LOGF_ERROR(
"Unknown error: maximum position value (%s)", res);
331 bool DeepSkyDadAF3::readSettleBuffer()
333 char res[DSD_RES] = {0};
335 if (sendCommand(
"[GBUF]", res) ==
false)
338 uint32_t settleBuffer = 0;
339 int rc = sscanf(res,
"(%d)", &settleBuffer);
342 SettleBufferN[0].value = settleBuffer;
347 LOGF_ERROR(
"Unknown error: settle buffer value (%s)", res);
354 bool DeepSkyDadAF3::readMoveCurrentMultiplier()
356 char res[DSD_RES] = {0};
358 if (sendCommand(
"[GMMM]", res) ==
false)
362 int rc = sscanf(res,
"(%d)", &mcm);
365 MoveCurrentMultiplierN[0].value = mcm;
366 MoveCurrentMultiplierNP.
s =
IPS_OK;
370 LOGF_ERROR(
"Unknown error: move current multiplier value (%s)", res);
377 bool DeepSkyDadAF3::readHoldCurrentMultiplier()
379 char res[DSD_RES] = {0};
381 if (sendCommand(
"[GMHM]", res) ==
false)
385 int rc = sscanf(res,
"(%d)", &hcm);
388 HoldCurrentMultiplierN[0].value = hcm;
389 HoldCurrentMultiplierNP.
s =
IPS_OK;
393 LOGF_ERROR(
"Unknown error: hold current multiplier value (%s)", res);
400 bool DeepSkyDadAF3::readTemperature()
402 char res[DSD_RES] = {0};
404 if (sendCommand(
"[GTMC]", res) ==
false)
408 int rc = sscanf(res,
"(%lf)", &temp);
411 TemperatureN[0].value = temp;
415 LOGF_ERROR(
"Unknown error: focuser temperature value (%s)", res);
422 bool DeepSkyDadAF3::isMoving()
424 char res[DSD_RES] = {0};
426 if (sendCommand(
"[GMOV]", res) ==
false)
429 if (strcmp(res,
"(1)") == 0)
431 else if (strcmp(res,
"(0)") == 0)
434 LOGF_ERROR(
"Unknown error: isMoving value (%s)", res);
440 char cmd[DSD_RES] = {0};
441 snprintf(
cmd, DSD_RES,
"[SPOS%07d]", ticks);
442 char res[DSD_RES] = {0};
443 return sendCommand(
cmd, res);
448 char cmd[DSD_RES] = {0};
449 snprintf(
cmd, DSD_RES,
"[SREV%01d]", enabled ? 1 : 0);
450 char res[DSD_RES] = {0};
451 return sendCommand(
cmd, res);
456 char cmd[DSD_RES] = {0};
457 char res[DSD_RES] = {0};
458 snprintf(
cmd, DSD_RES,
"[STRG%06d]", position);
460 if (sendCommand(
cmd, res) ==
false)
463 if(strcmp(res,
"!101)") == 0)
465 LOG_ERROR(
"MoveFocuserFailed - requested movement too big. You can increase the limit by changing the value of Max. movement.");
470 if (sendCommand(
"[SMOV]", res) ==
false)
481 if (strcmp(StepModeSP.
name, name) == 0)
489 if (current_mode == target_mode)
496 char cmd[DSD_RES] = {0};
500 else if(target_mode == 1)
502 else if(target_mode == 2)
504 else if(target_mode == 3)
506 else if(target_mode == 4)
508 else if(target_mode == 5)
510 else if(target_mode == 6)
512 else if(target_mode == 7)
514 else if(target_mode == 8)
517 snprintf(
cmd, DSD_RES,
"[SSTP%d]", target_mode);
518 bool rc = sendCommandSet(
cmd);
522 StepModeS[current_mode].s =
ISS_ON;
534 if (strcmp(SpeedModeSP.
name, name) == 0)
542 if (current_mode == target_mode)
549 char cmd[DSD_RES] = {0};
553 else if(target_mode == 1)
555 else if(target_mode == 2)
557 else if(target_mode == 3)
559 else if(target_mode == 4)
562 snprintf(
cmd, DSD_RES,
"[SSPD%d]", target_mode);
563 bool rc = sendCommandSet(
cmd);
567 SpeedModeS[current_mode].s =
ISS_ON;
587 if (strcmp(name, SettleBufferNP.
name) == 0)
590 char cmd[DSD_RES] = {0};
591 snprintf(
cmd, DSD_RES,
"[SBUF%06d]",
static_cast<int>(SettleBufferN[0].value));
592 bool rc = sendCommandSet(
cmd);
605 if (strcmp(name, MoveCurrentMultiplierNP.
name) == 0)
608 char cmd[DSD_RES] = {0};
609 snprintf(
cmd, DSD_RES,
"[SMMM%03d]",
static_cast<int>(MoveCurrentMultiplierN[0].value));
610 bool rc = sendCommandSet(
cmd);
617 MoveCurrentMultiplierNP.
s =
IPS_OK;
623 if (strcmp(name, HoldCurrentMultiplierNP.
name) == 0)
626 char cmd[DSD_RES] = {0};
627 snprintf(
cmd, DSD_RES,
"[SMHM%03d]",
static_cast<int>(HoldCurrentMultiplierN[0].value));
628 bool rc = sendCommandSet(
cmd);
635 HoldCurrentMultiplierNP.
s =
IPS_OK;
644 char cmd[DSD_RES] = {0};
645 snprintf(
cmd, DSD_RES,
"[SMXP%d]",
static_cast<int>(
FocusMaxPosN[0].value));
646 bool rc = sendCommandSet(
cmd);
681 void DeepSkyDadAF3::GetFocusParams()
695 if (readSettleBuffer())
698 if (readMoveCurrentMultiplier())
701 if (readHoldCurrentMultiplier())
704 if (readMaxPosition())
707 if (readMaxMovement())
710 if (readTemperature())
733 void DeepSkyDadAF3::timedMoveCallback()
748 targetPos = targetTicks;
752 if ((diff > 0 && bcValue < 0) || (diff < 0 && bcValue > 0))
754 backlashComp = bcValue;
755 targetPos -= bcValue;
766 int32_t newPosition = 0;
793 bool rc = readPosition();
807 if( backlashComp == 0 ) {
819 else if(backlashComp != 0)
821 LOGF_INFO(
"Performing backlash compensation of %i.", (
int)backlashComp);
822 targetPos += backlashComp;
827 LOG_INFO(
"Focuser reached requested position.");
835 rc = readTemperature();
839 if (std::abs(lastTemperature - TemperatureN[0].value) >= 0.1)
842 lastTemperature = TemperatureN[0].value;
852 return sendCommand(
"[STOP]");
857 Focuser::saveConfigItems(fp);
869 bool DeepSkyDadAF3::sendCommand(
const char *
cmd,
char * res)
871 int nbytes_written = 0, nbytes_read = 0, rc = -1;
873 tcflush(
PortFD, TCIOFLUSH);
881 LOGF_ERROR(
"Serial write error: %s.", errstr);
898 tcflush(
PortFD, TCIOFLUSH);
903 bool DeepSkyDadAF3::sendCommandSet(
const char *
cmd)
905 char res[DSD_RES] = {0};
907 if (sendCommand(
cmd, res) ==
false)
910 return strcmp(res,
"(OK)") == 0;
921 char cmd[DSD_RES] = {0};
923 snprintf(
cmd, DSD_RES,
"[SMXP%d]", ticks);
925 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
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
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
perform handshake with device to check communication
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
Process the client newSwitch command.
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.
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.
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.
INumber FocusBacklashN[1]
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.
virtual void SyncPresets(uint32_t ticks)
syncPresets Updates the min/max/step range of the preset as per the maximum name of Absolute Focus Tr...
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_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,...)