33 #define USBFOCUSV3_TIMEOUT 5
37 static std::unique_ptr<USBFocusV3> usbFocusV3(
new USBFocusV3());
83 TemperatureNP[0].
fill(
"TEMPERATURE",
"Celsius",
"%6.2f", -50., 70., 0., 0.);
88 MaxPositionNP[0].
fill(
"MAXPOSITION",
"Maximum position",
"%5.0f", 1., 65535., 0., 65535.);
93 TemperatureSettingNP[0].
fill(
"COEFFICIENT",
"Coefficient",
"%3.0f", 0., 999., 1., 15.);
94 TemperatureSettingNP[1].
fill(
"THRESHOLD",
"Threshold",
"%3.0f", 0., 999., 1., 10.);
105 TemperatureCompensateSP[0].
fill(
"ENABLE",
"Enable",
ISS_OFF);
106 TemperatureCompensateSP[1].
fill(
"DISABLE",
"Disable",
ISS_ON);
121 FWversionNP[0].
fill(
"FIRMWARE",
"Firmware Version",
"%5.0f", 0., 65535., 1., 0.);
164 LOG_INFO(
"USBFocusV3 parameters updated, focuser ready for use.");
190 LOG_INFO(
"USBFocusV3 is online. Getting focus parameters...");
193 LOG_INFO(
"Error retrieving data from USBFocusV3, trying resync...");
195 while (--tries > 0 && Resync());
197 LOG_INFO(
"Error retrieving data from USBFocusV3, please ensure controller "
198 "is powered and the port is correct.");
207 bool USBFocusV3::Resync()
210 int nbytes_written = 0, nbytes_read = 0, rc = -1;
217 tcflush(
PortFD, TCIOFLUSH);
219 for (
int resync = 0; resync <
UFOCMDLEN; resync++)
226 LOGF_ERROR(
"Error writing resync: %s.", errstr);
231 if (rc ==
TTY_OK && nbytes_read > 0)
242 bool USBFocusV3::sendCommand(
const char *
cmd,
char *resp)
244 pthread_mutex_lock(&cmdlock);
246 int nbytes_written = 0, nbytes_read = 0, rc = -1;
250 tcflush(
PortFD, TCIOFLUSH);
254 LOGF_WARN(
"Error writing command %s: %s.",
cmd, errstr);
255 pthread_mutex_unlock(&cmdlock);
264 LOGF_WARN(
"Error reading response for command %s: %s.",
cmd, errstr);
265 pthread_mutex_unlock(&cmdlock);
270 if (moving && nbytes_read > 0 && resp[0] ==
UFORSACK)
277 memmove(&resp[0], &resp[1], nbytes_read);
283 LOGF_WARN(
"Invalid response for command %s: %s.",
cmd, resp);
284 pthread_mutex_unlock(&cmdlock);
288 int rc = sscanf(resp,
"%s\n\r", resp);
291 LOGF_WARN(
"Invalid response for command %s: missing cr+lf",
cmd);
292 pthread_mutex_unlock(&cmdlock);
297 pthread_mutex_unlock(&cmdlock);
302 bool USBFocusV3::sendCommandSpecial(
const char *
cmd,
char *resp)
304 pthread_mutex_lock(&cmdlock);
306 int nbytes_written = 0, nbytes_read = 0, rc = -1;
310 tcflush(
PortFD, TCIOFLUSH);
314 LOGF_WARN(
"Error writing command %s: %s.",
cmd, errstr);
315 pthread_mutex_unlock(&cmdlock);
325 LOGF_WARN(
"Error reading response for command %s: %s.",
cmd, errstr);
326 pthread_mutex_unlock(&cmdlock);
329 resp[nbytes_read] =
'\0';
332 pthread_mutex_unlock(&cmdlock);
336 bool USBFocusV3::Ack()
339 tcflush(
PortFD, TCIOFLUSH);
346 LOGF_ERROR(
"USBFocusV3 not properly identified! Answer was: %s.", resp);
358 sscanf(resp,
"C=%u-%u-%u-%u-%u-%u-%u", &direction, &stepmode, &speed, &stepsdeg, &tcomp_thr, &firmware, &maxpos);
362 bool USBFocusV3::updateStepMode()
372 LOGF_ERROR(
"Unknown error: focuser step value (%d)", stepmode);
378 bool USBFocusV3::updateRotDir()
388 LOGF_ERROR(
"Unknown error: rotation direction (%d)", direction);
395 bool USBFocusV3::updateTemperature()
409 int rc = sscanf(resp,
"T=%f", &temp);
413 TemperatureNP[0].setValue(temp);
418 LOGF_DEBUG(
"Unknown error: focuser temperature value (%s)", resp);
425 LOGF_ERROR(
"Unknown error: focuser temperature value (%s)", resp);
432 bool USBFocusV3::updateFWversion()
434 FWversionNP[0].setValue(firmware);
438 bool USBFocusV3::updatePosition()
452 int rc = sscanf(resp,
"P=%u", &pos);
461 LOGF_DEBUG(
"Unknown error: focuser position value (%s)", resp);
468 LOGF_ERROR(
"Unknown error: focuser position value (%s)", resp);
475 bool USBFocusV3::updateMaxPos()
477 MaxPositionNP[0].setValue(maxpos);
482 bool USBFocusV3::updateTempCompSettings()
484 TemperatureSettingNP[0].setValue(stepsdeg);
485 TemperatureSettingNP[1].setValue(tcomp_thr);
489 bool USBFocusV3::updateTempCompSign()
499 int rc = sscanf(resp,
"A=%u", &sign);
503 TempCompSignSP.
reset();
511 LOGF_ERROR(
"Unknown error: temp. comp. sign (%d)", sign);
517 LOGF_ERROR(
"Unknown error: temp. comp. sign value (%s)", resp);
524 bool USBFocusV3::updateSpeed()
546 currentSpeed = drvspeed;
551 LOGF_ERROR(
"Unknown error: focuser speed value (%d)", speed);
558 bool USBFocusV3::setAutoTempCompThreshold(
unsigned int thr)
564 if (!sendCommand(
cmd, resp))
573 LOG_ERROR(
"setAutoTempCompThreshold error: did not receive DONE.");
578 bool USBFocusV3::setTemperatureCoefficient(
unsigned int coefficient)
584 if (!sendCommand(
cmd, resp))
589 stepsdeg = coefficient;
593 LOG_ERROR(
"setTemperatureCoefficient error: did not receive DONE.");
598 bool USBFocusV3::reset()
609 bool USBFocusV3::MoveFocuserUF(FocusDirection dir,
unsigned int rticks)
618 LOGF_WARN(
"Requested %u ticks but inward movement has been limited to %u ticks", rticks, ticks);
622 ticks = MaxPositionNP[0].getValue() -
FocusAbsPosN[0].value;
623 LOGF_WARN(
"Requested %u ticks but outward movement has been limited to %u ticks", rticks, ticks);
632 if (backlashMove ==
false && backlashIn ==
true && backlashSteps != 0)
634 ticks += backlashSteps;
635 backlashTargetPos = targetPos - backlashSteps;
642 if (backlashMove ==
false && backlashIn ==
false && backlashSteps != 0)
644 ticks += backlashSteps;
645 backlashTargetPos = targetPos + backlashSteps;
651 return sendCommand(
cmd,
nullptr);
654 bool USBFocusV3::setStepMode(FocusStepMode mode)
664 if (!sendCommand(
cmd, resp))
671 bool USBFocusV3::setRotDir(
unsigned int dir)
681 if (!sendCommand(
cmd, resp))
688 bool USBFocusV3::setMaxPos(
unsigned int maxp)
693 if (maxp >= 1 && maxp <= 65535)
699 LOGF_ERROR(
"Focuser max. pos. value %d out of bounds", maxp);
703 if (!sendCommand(
cmd, resp))
713 LOG_ERROR(
"setMaxPos error: did not receive DONE.");
718 bool USBFocusV3::setSpeed(
unsigned short drvspeed)
747 LOGF_ERROR(
"Focuser speed value %d out of bounds", drvspeed);
751 if (!sendCommand(
cmd, resp))
760 LOG_ERROR(
"setSpeed error: did not receive DONE.");
765 bool USBFocusV3::setTemperatureCompensation(
bool enable)
775 if (!sendCommand(
cmd, resp))
781 bool USBFocusV3::setTempCompSign(
unsigned int sign)
788 if (!sendCommand(
cmd, resp))
796 LOG_ERROR(
"setTempCompSign error: did not receive DONE.");
809 StepModeSP.
update(states, names, n);
811 if (current_mode != target_mode)
836 RotDirSP.
update(states, names, n);
838 if (current_mode != target_mode)
840 if (!setRotDir(target_mode))
858 TemperatureCompensateSP.
update(states, names, n);
861 if (last_index != target_index)
863 if (!setTemperatureCompensation((TemperatureCompensateSP[0].getState() ==
ISS_ON)))
866 TemperatureCompensateSP.
reset();
868 TemperatureCompensateSP.
apply();
873 TemperatureCompensateSP.
apply();
880 TempCompSignSP.
update(states, names, n);
882 if (current_mode != target_mode)
884 if (!setTempCompSign(target_mode))
886 TempCompSignSP.
reset();
889 TempCompSignSP.
apply();
894 TempCompSignSP.
apply();
920 MaxPositionNP.
update(values, names, n);
921 if (!setMaxPos(MaxPositionNP[0].getValue()))
924 MaxPositionNP.
apply();
928 MaxPositionNP.
apply();
934 TemperatureSettingNP.
update(values, names, n);
935 if (!setAutoTempCompThreshold(TemperatureSettingNP[1].getValue()) ||
936 !setTemperatureCoefficient(TemperatureSettingNP[
UFOPNSIGN].getValue()))
939 TemperatureSettingNP.
apply();
944 TemperatureSettingNP.
apply();
950 void USBFocusV3::GetFocusParams()
954 if (updatePosition())
959 MaxPositionNP.
apply();
963 if (updateTemperature())
964 TemperatureNP.
apply();
966 if (updateTempCompSettings())
967 TemperatureSettingNP.
apply();
969 if (updateTempCompSign())
970 TempCompSignSP.
apply();
975 if (updateStepMode())
981 if (updateFWversion())
987 if (!setSpeed(speed))
990 currentSpeed = speed;
1002 targetPos = targetTicks;
1029 "Requested %u ticks but relative inward movement has been limited to %u ticks", ticks, aticks);
1034 aticks = MaxPositionNP[0].getValue() -
FocusAbsPosN[0].value;
1036 "Requested %u ticks but relative outward movement has been limited to %u ticks", ticks, aticks);
1040 if (!MoveFocuserUF(dir, (
unsigned int)ticks))
1056 if (updatePosition())
1065 if (updateTemperature())
1067 if (fabs(lastTemperature - TemperatureNP[0].getValue()) >= 0.5)
1069 TemperatureNP.
apply();
1070 lastTemperature = TemperatureNP[0].getValue();
1076 float remaining = CalcTimeLeft(focusMoveStart, focusMoveRequest);
1092 if (backlashMove && (fabs(backlashTargetPos -
FocusAbsPosN[0].value) < 1))
1096 backlashMove =
false;
1107 LOG_INFO(
"Focuser reached requested position.");
1125 backlashMove =
false;
1130 float USBFocusV3::CalcTimeLeft(timeval start,
float req)
1138 gettimeofday(&now,
nullptr);
1141 (double)(now.tv_sec * 1000.0 + now.tv_usec / 1000) - (double)(start.tv_sec * 1000.0 + start.tv_usec / 1000);
1142 timesince = timesince / 1000;
1143 timeleft = req - timesince;
1149 backlashIn = steps < 0;
1150 backlashSteps = std::abs(steps);
const char * getDeviceName() const
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool loadConfig(bool silent=false, const char *property=nullptr)
Load the last saved configuration file.
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 FocusSpeedNP
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]
@ FOCUSER_HAS_VARIABLE_SPEED
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.
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
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)
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.
bool getControllerStatus()
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual const char * getDefaultName() override
virtual bool Handshake() override
perform handshake with device to check communication
virtual bool SetFocuserSpeed(int speed) override
SetFocuserSpeed Set Focuser speed.
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 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
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 IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
#define LOGF_INFO(fmt,...)
#define LOGF_WARN(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,...)
#define USBFOCUSV3_TIMEOUT