Instrument Neutral Distributed Interface INDI  1.9.5
usbfocusv3.cpp
Go to the documentation of this file.
1 /*
2  USB Focus V3
3  Copyright (C) 2016 G. Schmidt
4  Copyright (C) 2018 Jarno Paananen
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either
9  version 2.1 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 
20 */
21 
22 #include "usbfocusv3.h"
23 
24 #include "indicom.h"
25 
26 #include <cmath>
27 #include <cstring>
28 #include <memory>
29 
30 #include <termios.h>
31 #include <unistd.h>
32 
33 #define USBFOCUSV3_TIMEOUT 5
34 
35 /***************************** Class USBFocusV3 *******************************/
36 
37 static std::unique_ptr<USBFocusV3> usbFocusV3(new USBFocusV3());
38 
40 {
41  // Can move in Absolute & Relative motions, can AbortFocuser motion, and has variable speed.
47 }
48 
50 {
52 
53  /*** init controller parameters ***/
54 
55  direction = 0;
56  stepmode = 1;
57  speed = 3;
58  stepsdeg = 20;
59  tcomp_thr = 5;
60  firmware = 0;
61  maxpos = 65535;
62 
63  /*** init driver parameters ***/
64 
65  FocusSpeedN[0].min = 1;
66  FocusSpeedN[0].max = 3;
67  FocusSpeedN[0].value = 2;
68 
69  // Step Mode
70  IUFillSwitch(&StepModeS[UFOPHSTEPS], "HALF", "Half Step", ISS_ON);
71  IUFillSwitch(&StepModeS[UFOPFSTEPS], "FULL", "Full Step", ISS_OFF);
72  IUFillSwitchVector(&StepModeSP, StepModeS, 2, getDeviceName(), "STEP_MODE", "Step Mode", OPTIONS_TAB, IP_RW,
73  ISR_1OFMANY, 0, IPS_IDLE);
74 
75  // Direction
76  IUFillSwitch(&RotDirS[UFOPSDIR], "STANDARD", "Standard rotation", ISS_ON);
77  IUFillSwitch(&RotDirS[UFOPRDIR], "REVERSE", "Reverse rotation", ISS_OFF);
78  IUFillSwitchVector(&RotDirSP, RotDirS, 2, getDeviceName(), "ROTATION_MODE", "Rotation Mode", OPTIONS_TAB, IP_RW,
79  ISR_1OFMANY, 0, IPS_IDLE);
80 
81  // Focuser temperature
82  IUFillNumber(&TemperatureN[0], "TEMPERATURE", "Celsius", "%6.2f", -50., 70., 0., 0.);
83  IUFillNumberVector(&TemperatureNP, TemperatureN, 1, getDeviceName(), "FOCUS_TEMPERATURE", "Temperature",
85 
86  // Maximum Position
87  IUFillNumber(&MaxPositionN[0], "MAXPOSITION", "Maximum position", "%5.0f", 1., 65535., 0., 65535.);
88  IUFillNumberVector(&MaxPositionNP, MaxPositionN, 1, getDeviceName(), "FOCUS_MAXPOSITION", "Max. Position",
90 
91  // Temperature Settings
92  IUFillNumber(&TemperatureSettingN[0], "COEFFICIENT", "Coefficient", "%3.0f", 0., 999., 1., 15.);
93  IUFillNumber(&TemperatureSettingN[1], "THRESHOLD", "Threshold", "%3.0f", 0., 999., 1., 10.);
94  IUFillNumberVector(&TemperatureSettingNP, TemperatureSettingN, 2, getDeviceName(), "TEMPERATURE_SETTINGS",
95  "Temp. Settings", OPTIONS_TAB, IP_RW, 0, IPS_IDLE);
96 
97  // Temperature Compensation Sign
98  IUFillSwitch(&TempCompSignS[UFOPNSIGN], "NEGATIVE", "Negative", ISS_OFF);
99  IUFillSwitch(&TempCompSignS[UFOPPSIGN], "POSITIVE", "Positive", ISS_ON);
100  IUFillSwitchVector(&TempCompSignSP, TempCompSignS, 2, getDeviceName(), "TCOMP_SIGN", "TComp. Sign", OPTIONS_TAB,
101  IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
102 
103  // Compensate for temperature
104  IUFillSwitch(&TemperatureCompensateS[0], "ENABLE", "Enable", ISS_OFF);
105  IUFillSwitch(&TemperatureCompensateS[1], "DISABLE", "Disable", ISS_ON);
106  IUFillSwitchVector(&TemperatureCompensateSP, TemperatureCompensateS, 2, getDeviceName(), "TEMP_COMPENSATION",
107  "Temp. Comp.", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
108 
109  // Compensate for temperature
110  // IUFillSwitch(&BacklashDirectionS[BACKLASH_IN], "IN", "In", ISS_OFF);
111  // IUFillSwitch(&BacklashDirectionS[BACKLASH_OUT], "OUT", "Out", ISS_ON);
112  // IUFillSwitchVector(&BacklashDirectionSP, BacklashDirectionS, 2, getDeviceName(), "BACKLASH_DIRECTION",
113  // "Backlash direction", OPTIONS_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
114 
115  // // Backlash compensation steps
116  // IUFillNumber(&BacklashSettingN[0], "FOCUS_BACKLASH_VALUE", "Steps", "%5.0f", 0., 65535., 1., 0.);
117  // IUFillNumberVector(&BacklashSettingNP, BacklashSettingN, 1, getDeviceName(), "FOCUS_BACKLASH_STEPS", "Backlash steps",
118  // OPTIONS_TAB, IP_RW, 0, IPS_IDLE);
119 
120  FocusBacklashN[0].min = -65535.;
121  FocusBacklashN[0].max = 65535.;
122  FocusBacklashN[0].step = 1000.;
123  FocusBacklashN[0].value = 0.;
124 
125  // Reset
126  IUFillSwitch(&ResetS[0], "RESET", "Reset", ISS_OFF);
127  IUFillSwitchVector(&ResetSP, ResetS, 1, getDeviceName(), "RESET", "Reset", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0,
128  IPS_IDLE);
129 
130  // Firmware version
131  IUFillNumber(&FWversionN[0], "FIRMWARE", "Firmware Version", "%5.0f", 0., 65535., 1., 0.);
132  IUFillNumberVector(&FWversionNP, FWversionN, 1, getDeviceName(), "FW_VERSION", "Firmware", OPTIONS_TAB, IP_RO, 0,
133  IPS_IDLE);
134 
135  /* Relative and absolute movement */
136  FocusRelPosN[0].min = 0.;
137  FocusRelPosN[0].max = float(maxpos);
138  FocusRelPosN[0].value = 0;
139  FocusRelPosN[0].step = 1;
140 
141  FocusAbsPosN[0].min = 0.;
142  FocusAbsPosN[0].max = float(maxpos);
143  FocusAbsPosN[0].value = 0;
144  FocusAbsPosN[0].step = 1;
145 
146  addDebugControl();
147 
149 
150  return true;
151 }
152 
154 {
156 
157  if (isConnected())
158  {
159  defineProperty(&TemperatureNP);
160  defineProperty(&MaxPositionNP);
161  defineProperty(&StepModeSP);
162  defineProperty(&RotDirSP);
163  defineProperty(&MaxPositionNP);
164  defineProperty(&TemperatureSettingNP);
165  defineProperty(&TempCompSignSP);
166  defineProperty(&TemperatureCompensateSP);
167  // defineProperty(&BacklashDirectionSP);
168  // defineProperty(&BacklashSettingNP);
169  defineProperty(&ResetSP);
170  defineProperty(&FWversionNP);
171 
172  GetFocusParams();
173 
174  loadConfig(true);
175 
176  LOG_INFO("USBFocusV3 parameters updated, focuser ready for use.");
177  }
178  else
179  {
180  deleteProperty(TemperatureNP.name);
181  deleteProperty(MaxPositionNP.name);
182  deleteProperty(StepModeSP.name);
183  deleteProperty(RotDirSP.name);
184  deleteProperty(TemperatureSettingNP.name);
185  deleteProperty(TempCompSignSP.name);
186  deleteProperty(TemperatureCompensateSP.name);
187  // deleteProperty(BacklashDirectionSP.name);
188  // deleteProperty(BacklashSettingNP.name);
189  deleteProperty(ResetSP.name);
190  deleteProperty(FWversionNP.name);
191  }
192 
193  return true;
194 }
195 
197 {
198  int tries = 2;
199 
200  do
201  {
202  if (Ack())
203  {
204  LOG_INFO("USBFocusV3 is online. Getting focus parameters...");
205  return true;
206  }
207  LOG_INFO("Error retrieving data from USBFocusV3, trying resync...");
208  }
209  while (--tries > 0 && Resync());
210 
211  LOG_INFO("Error retrieving data from USBFocusV3, please ensure controller "
212  "is powered and the port is correct.");
213  return false;
214 }
215 
217 {
218  return "USBFocusV3";
219 }
220 
221 bool USBFocusV3::Resync()
222 {
223  char cmd[] = " "; // Illegal command to trigger error response
224  int nbytes_written = 0, nbytes_read = 0, rc = -1;
225  char errstr[MAXRBUF];
226  char resp[UFORESLEN] = {};
227 
228  // Send up to 5 space characters and wait for error
229  // response ("ER=1") after which the communication
230  // is back in sync
231  tcflush(PortFD, TCIOFLUSH);
232 
233  for (int resync = 0; resync < UFOCMDLEN; resync++)
234  {
235  LOGF_INFO("Retry %d...", resync + 1);
236 
237  if ((rc = tty_write(PortFD, cmd, 1, &nbytes_written)) != TTY_OK)
238  {
239  tty_error_msg(rc, errstr, MAXRBUF);
240  LOGF_ERROR("Error writing resync: %s.", errstr);
241  return false;
242  }
243 
244  rc = tty_nread_section(PortFD, resp, UFORESLEN, '\r', 3, &nbytes_read);
245  if (rc == TTY_OK && nbytes_read > 0)
246  {
247  // We got a response
248  return true;
249  }
250  // We didn't get response yet, retry
251  }
252  LOG_ERROR("No valid resync response.");
253  return false;
254 }
255 
256 bool USBFocusV3::sendCommand(const char *cmd, char *resp)
257 {
258  pthread_mutex_lock(&cmdlock);
259 
260  int nbytes_written = 0, nbytes_read = 0, rc = -1;
261  char errstr[MAXRBUF];
262  LOGF_DEBUG("CMD: %s.", cmd);
263 
264  tcflush(PortFD, TCIOFLUSH);
265  if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
266  {
267  tty_error_msg(rc, errstr, MAXRBUF);
268  LOGF_WARN("Error writing command %s: %s.", cmd, errstr);
269  pthread_mutex_unlock(&cmdlock);
270  return false;
271  }
272 
273  if (resp)
274  {
275  if ((rc = tty_nread_section(PortFD, resp, UFORESLEN, '\r', USBFOCUSV3_TIMEOUT, &nbytes_read)) != TTY_OK)
276  {
277  tty_error_msg(rc, errstr, MAXRBUF);
278  LOGF_WARN("Error reading response for command %s: %s.", cmd, errstr);
279  pthread_mutex_unlock(&cmdlock);
280  return false;
281  }
282 
283  // If we are moving, check for ACK * response first
284  if (moving && nbytes_read > 0 && resp[0] == UFORSACK)
285  {
286  moving = false;
287  if (nbytes_read > 1)
288  {
289  // Move rest of the response down one byte
290  nbytes_read--;
291  memmove(&resp[0], &resp[1], nbytes_read);
292  }
293  }
294 
295  if (nbytes_read < 2)
296  {
297  LOGF_WARN("Invalid response for command %s: %s.", cmd, resp);
298  pthread_mutex_unlock(&cmdlock);
299  return false;
300  }
301  // Be sure we receive the \n\r to not truncate the response
302  int rc = sscanf(resp, "%s\n\r", resp);
303  if (rc <= 0)
304  {
305  LOGF_WARN("Invalid response for command %s: missing cr+lf", cmd);
306  pthread_mutex_unlock(&cmdlock);
307  return false;
308  }
309  LOGF_DEBUG("RES: %s.", resp);
310  }
311  pthread_mutex_unlock(&cmdlock);
312  return true;
313 }
314 
315 // Special version to work around command FTAXXA, which replies without \n\r
316 bool USBFocusV3::sendCommandSpecial(const char *cmd, char *resp)
317 {
318  pthread_mutex_lock(&cmdlock);
319 
320  int nbytes_written = 0, nbytes_read = 0, rc = -1;
321  char errstr[MAXRBUF];
322  LOGF_DEBUG("CMD: %s.", cmd);
323 
324  tcflush(PortFD, TCIOFLUSH);
325  if ((rc = tty_write(PortFD, cmd, strlen(cmd), &nbytes_written)) != TTY_OK)
326  {
327  tty_error_msg(rc, errstr, MAXRBUF);
328  LOGF_WARN("Error writing command %s: %s.", cmd, errstr);
329  pthread_mutex_unlock(&cmdlock);
330  return false;
331  }
332 
333  if (resp)
334  {
335  // We assume answer A=x where x is 0 or 1
336  if ((rc = tty_read(PortFD, resp, 3, USBFOCUSV3_TIMEOUT, &nbytes_read)) != TTY_OK)
337  {
338  tty_error_msg(rc, errstr, MAXRBUF);
339  LOGF_WARN("Error reading response for command %s: %s.", cmd, errstr);
340  pthread_mutex_unlock(&cmdlock);
341  return false;
342  }
343  resp[nbytes_read] = '\0';
344  LOGF_DEBUG("RES: %s.", resp);
345  }
346  pthread_mutex_unlock(&cmdlock);
347  return true;
348 }
349 
350 bool USBFocusV3::Ack()
351 {
352  char resp[UFORESLEN] = {};
353  tcflush(PortFD, TCIOFLUSH);
354 
355  if (!sendCommand(UFOCDEVID, resp))
356  return false;
357 
358  if (strncmp(resp, UFOID, UFORESLEN) != 0)
359  {
360  LOGF_ERROR("USBFocusV3 not properly identified! Answer was: %s.", resp);
361  return false;
362  }
363  return true;
364 }
365 
367 {
368  char resp[UFORESLEN] = {};
369  if (!sendCommand(UFOCREADPARAM, resp))
370  return false;
371 
372  sscanf(resp, "C=%u-%u-%u-%u-%u-%u-%u", &direction, &stepmode, &speed, &stepsdeg, &tcomp_thr, &firmware, &maxpos);
373  return true;
374 }
375 
376 bool USBFocusV3::updateStepMode()
377 {
378  IUResetSwitch(&StepModeSP);
379 
380  if (stepmode == UFOPHSTEPS)
381  StepModeS[UFOPHSTEPS].s = ISS_ON;
382  else if (stepmode == UFOPFSTEPS)
383  StepModeS[UFOPFSTEPS].s = ISS_ON;
384  else
385  {
386  LOGF_ERROR("Unknown error: focuser step value (%d)", stepmode);
387  return false;
388  }
389 
390  return true;
391 }
392 
393 bool USBFocusV3::updateRotDir()
394 {
395  IUResetSwitch(&RotDirSP);
396 
397  if (direction == UFOPSDIR)
398  RotDirS[UFOPSDIR].s = ISS_ON;
399  else if (direction == UFOPRDIR)
400  RotDirS[UFOPRDIR].s = ISS_ON;
401  else
402  {
403  LOGF_ERROR("Unknown error: rotation direction (%d)", direction);
404  return false;
405  }
406 
407  return true;
408 }
409 
410 bool USBFocusV3::updateTemperature()
411 {
412  char resp[UFORESLEN] = {};
413  int j = 0;
414 
415  // retry up to 5 time to fix data desyncronization.
416  // see: https://bitbucket.org/usb-focus/ascom-driver/src/f0ec7d0faee605f9a3d9e2c4d599f9d537211201/USB_Focus/Driver.cs?at=master&fileviewer=file-view-default#Driver.cs-898
417 
418  while (j <= 5)
419  {
420  if (sendCommand(UFOCREADTEMP, resp))
421  {
422 
423  float temp;
424  int rc = sscanf(resp, "T=%f", &temp);
425 
426  if (rc > 0)
427  {
428  TemperatureN[0].value = temp;
429  break;
430  }
431  else
432  {
433  LOGF_DEBUG("Unknown error: focuser temperature value (%s)", resp);
434  }
435  }
436  j++;
437  }
438  if (j > 5)
439  {
440  LOGF_ERROR("Unknown error: focuser temperature value (%s)", resp);
441  return false;
442  }
443 
444  return true;
445 }
446 
447 bool USBFocusV3::updateFWversion()
448 {
449  FWversionN[0].value = firmware;
450  return true;
451 }
452 
453 bool USBFocusV3::updatePosition()
454 {
455  char resp[UFORESLEN] = {};
456  int j = 0;
457 
458  // retry up to 5 time to fix data desyncronization.
459  // see: https://bitbucket.org/usb-focus/ascom-driver/src/f0ec7d0faee605f9a3d9e2c4d599f9d537211201/USB_Focus/Driver.cs?at=master&fileviewer=file-view-default#Driver.cs-746
460 
461  while (j <= 5)
462  {
463  if (sendCommand(UFOCREADPOS, resp))
464  {
465 
466  int pos = -1;
467  int rc = sscanf(resp, "P=%u", &pos);
468 
469  if (rc > 0)
470  {
471  FocusAbsPosN[0].value = pos;
472  break;
473  }
474  else
475  {
476  LOGF_DEBUG("Unknown error: focuser position value (%s)", resp);
477  }
478  }
479  j++;
480  }
481  if (j > 5)
482  {
483  LOGF_ERROR("Unknown error: focuser position value (%s)", resp);
484  return false;
485  }
486 
487  return true;
488 }
489 
490 bool USBFocusV3::updateMaxPos()
491 {
492  MaxPositionN[0].value = maxpos;
493  FocusAbsPosN[0].max = maxpos;
494  return true;
495 }
496 
497 bool USBFocusV3::updateTempCompSettings()
498 {
499  TemperatureSettingN[0].value = stepsdeg;
500  TemperatureSettingN[1].value = tcomp_thr;
501  return true;
502 }
503 
504 bool USBFocusV3::updateTempCompSign()
505 {
506  char resp[UFORESLEN] = {};
507  // This command seems to have a bug in firmware 1505 that it
508  // doesn't send \n\r in reply like all others except movement
509  // commands so use a special version for it
510  if (!sendCommandSpecial(UFOCGETSIGN, resp))
511  return false;
512 
513  unsigned int sign;
514  int rc = sscanf(resp, "A=%u", &sign);
515 
516  if (rc > 0)
517  {
518  IUResetSwitch(&TempCompSignSP);
519 
520  if (sign == UFOPNSIGN)
521  TempCompSignS[UFOPNSIGN].s = ISS_ON;
522  else if (sign == UFOPPSIGN)
523  TempCompSignS[UFOPPSIGN].s = ISS_ON;
524  else
525  {
526  LOGF_ERROR("Unknown error: temp. comp. sign (%d)", sign);
527  return false;
528  }
529  }
530  else
531  {
532  LOGF_ERROR("Unknown error: temp. comp. sign value (%s)", resp);
533  return false;
534  }
535 
536  return true;
537 }
538 
539 bool USBFocusV3::updateSpeed()
540 {
541  int drvspeed;
542 
543  switch (speed)
544  {
545  case UFOPSPDAV:
546  drvspeed = 3;
547  break;
548  case UFOPSPDSL:
549  drvspeed = 2;
550  break;
551  case UFOPSPDUS:
552  drvspeed = 1;
553  break;
554  default:
555  drvspeed = 0;
556  break;
557  }
558 
559  if (drvspeed != 0)
560  {
561  currentSpeed = drvspeed;
562  FocusSpeedN[0].value = drvspeed;
563  }
564  else
565  {
566  LOGF_ERROR("Unknown error: focuser speed value (%d)", speed);
567  return false;
568  }
569 
570  return true;
571 }
572 
573 bool USBFocusV3::setAutoTempCompThreshold(unsigned int thr)
574 {
575  char cmd[UFOCMDLEN + 1];
576  snprintf(cmd, UFOCMDLEN + 1, UFOCSETTCTHR, thr);
577 
578  char resp[UFORESLEN] = {};
579  if (!sendCommand(cmd, resp))
580  return false;
581 
582  if (strncmp(resp, UFORSDONE, strlen(UFORSDONE)) == 0)
583  {
584  tcomp_thr = thr;
585  return true;
586  }
587 
588  LOG_ERROR("setAutoTempCompThreshold error: did not receive DONE.");
589 
590  return false;
591 }
592 
593 bool USBFocusV3::setTemperatureCoefficient(unsigned int coefficient)
594 {
595  char cmd[UFOCMDLEN + 1];
596  snprintf(cmd, UFOCMDLEN + 1, UFOCSETSTDEG, coefficient);
597 
598  char resp[UFORESLEN] = {};
599  if (!sendCommand(cmd, resp))
600  return false;
601 
602  if (strncmp(resp, UFORSDONE, strlen(UFORSDONE)) == 0)
603  {
604  stepsdeg = coefficient;
605  return true;
606  }
607 
608  LOG_ERROR("setTemperatureCoefficient error: did not receive DONE.");
609 
610  return false;
611 }
612 
613 bool USBFocusV3::reset()
614 {
615  char resp[UFORESLEN] = {};
616  if (!sendCommand(UFOCRESET, resp))
617  return false;
618 
619  GetFocusParams();
620 
621  return true;
622 }
623 
624 bool USBFocusV3::MoveFocuserUF(FocusDirection dir, unsigned int rticks)
625 {
626  char cmd[UFOCMDLEN + 1];
627 
628  unsigned int ticks;
629 
630  if ((dir == FOCUS_INWARD) && (rticks > FocusAbsPosN[0].value))
631  {
632  ticks = FocusAbsPosN[0].value;
633  LOGF_WARN("Requested %u ticks but inward movement has been limited to %u ticks", rticks, ticks);
634  }
635  else if ((dir == FOCUS_OUTWARD) && ((FocusAbsPosN[0].value + rticks) > MaxPositionN[0].value))
636  {
637  ticks = MaxPositionN[0].value - FocusAbsPosN[0].value;
638  LOGF_WARN("Requested %u ticks but outward movement has been limited to %u ticks", rticks, ticks);
639  }
640  else
641  {
642  ticks = rticks;
643  }
644 
645  if (dir == FOCUS_INWARD)
646  {
647  if (backlashMove == false && backlashIn == true && backlashSteps != 0)
648  {
649  ticks += backlashSteps;
650  backlashTargetPos = targetPos - backlashSteps;
651  backlashMove = true;
652  }
653  snprintf(cmd, UFOCMDLEN + 1, UFOCMOVEIN, ticks);
654  }
655  else
656  {
657  if (backlashMove == false && backlashIn == false && backlashSteps != 0)
658  {
659  ticks += backlashSteps;
660  backlashTargetPos = targetPos + backlashSteps;
661  backlashMove = true;
662  }
663  snprintf(cmd, UFOCMDLEN + 1, UFOCMOVEOUT, ticks);
664  }
665  moving = true;
666  return sendCommand(cmd, nullptr);
667 }
668 
669 bool USBFocusV3::setStepMode(FocusStepMode mode)
670 {
671  char resp[UFORESLEN] = {};
672  char cmd[UFOCMDLEN + 1];
673 
674  if (mode == FOCUS_HALF_STEP)
675  snprintf(cmd, UFOCMDLEN + 1, "%s", UFOCSETHSTEPS);
676  else
677  snprintf(cmd, UFOCMDLEN + 1, "%s", UFOCSETFSTEPS);
678 
679  if (!sendCommand(cmd, resp))
680  return false;
681 
682  stepmode = mode;
683  return true;
684 }
685 
686 bool USBFocusV3::setRotDir(unsigned int dir)
687 {
688  char resp[UFORESLEN] = {};
689  char cmd[UFOCMDLEN + 1];
690 
691  if (dir == UFOPSDIR)
692  snprintf(cmd, UFOCMDLEN + 1, "%s", UFOCSETSDIR);
693  else
694  snprintf(cmd, UFOCMDLEN + 1, "%s", UFOCSETRDIR);
695 
696  if (!sendCommand(cmd, resp))
697  return false;
698 
699  direction = dir;
700  return true;
701 }
702 
703 bool USBFocusV3::setMaxPos(unsigned int maxp)
704 {
705  char cmd[UFOCMDLEN + 1];
706  char resp[UFORESLEN] = {};
707 
708  if (maxp >= 1 && maxp <= 65535)
709  {
710  snprintf(cmd, UFOCMDLEN + 1, UFOCSETMAX, maxp);
711  }
712  else
713  {
714  LOGF_ERROR("Focuser max. pos. value %d out of bounds", maxp);
715  return false;
716  }
717 
718  if (!sendCommand(cmd, resp))
719  return false;
720 
721  if (strncmp(resp, UFORSDONE, strlen(UFORSDONE)) == 0)
722  {
723  maxpos = maxp;
724  FocusAbsPosN[0].max = maxpos;
725  return true;
726  }
727 
728  LOG_ERROR("setMaxPos error: did not receive DONE.");
729 
730  return false;
731 }
732 
733 bool USBFocusV3::setSpeed(unsigned short drvspeed)
734 {
735  char cmd[UFOCMDLEN + 1];
736  char resp[UFORESLEN] = {};
737 
738  unsigned int spd;
739 
740  switch (drvspeed)
741  {
742  case 3:
743  spd = UFOPSPDAV;
744  break;
745  case 2:
746  spd = UFOPSPDSL;
747  break;
748  case 1:
749  spd = UFOPSPDUS;
750  break;
751  default:
752  spd = UFOPSPDERR;
753  break;
754  }
755 
756  if (spd != UFOPSPDERR)
757  {
758  snprintf(cmd, UFOCMDLEN + 1, UFOCSETSPEED, spd);
759  }
760  else
761  {
762  LOGF_ERROR("Focuser speed value %d out of bounds", drvspeed);
763  return false;
764  }
765 
766  if (!sendCommand(cmd, resp))
767  return false;
768 
769  if (strncmp(resp, UFORSDONE, strlen(UFORSDONE)) == 0)
770  {
771  speed = spd;
772  return true;
773  }
774 
775  LOG_ERROR("setSpeed error: did not receive DONE.");
776 
777  return false;
778 }
779 
780 bool USBFocusV3::setTemperatureCompensation(bool enable)
781 {
782  char cmd[UFOCMDLEN + 1];
783  char resp[UFORESLEN] = {};
784 
785  if (enable)
786  snprintf(cmd, UFOCMDLEN + 1, "%s", UFOCSETAUTO);
787  else
788  snprintf(cmd, UFOCMDLEN + 1, "%s", UFOCSETMANU);
789 
790  if (!sendCommand(cmd, resp))
791  return false;
792 
793  return true;
794 }
795 
796 bool USBFocusV3::setTempCompSign(unsigned int sign)
797 {
798  char cmd[UFOCMDLEN + 1];
799  char resp[UFORESLEN] = {};
800 
801  snprintf(cmd, UFOCMDLEN + 1, UFOCSETSIGN, sign);
802 
803  if (!sendCommand(cmd, resp))
804  return false;
805 
806  if (strncmp(resp, UFORSDONE, strlen(UFORSDONE)) == 0)
807  {
808  return true;
809  }
810 
811  LOG_ERROR("setTempCompSign error: did not receive DONE.");
812 
813  return false;
814 }
815 
816 bool USBFocusV3::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
817 {
818  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
819  {
820  if (strcmp(StepModeSP.name, name) == 0)
821  {
822  bool rc = false;
823  int current_mode = IUFindOnSwitchIndex(&StepModeSP);
824  IUUpdateSwitch(&StepModeSP, states, names, n);
825  int target_mode = IUFindOnSwitchIndex(&StepModeSP);
826  if (current_mode == target_mode)
827  {
828  StepModeSP.s = IPS_OK;
829  IDSetSwitch(&StepModeSP, nullptr);
830  return true;
831  }
832 
833  if (target_mode == UFOPHSTEPS)
834  rc = setStepMode(FOCUS_HALF_STEP);
835  else
836  rc = setStepMode(FOCUS_FULL_STEP);
837 
838  if (!rc)
839  {
840  IUResetSwitch(&StepModeSP);
841  StepModeS[current_mode].s = ISS_ON;
842  StepModeSP.s = IPS_ALERT;
843  IDSetSwitch(&StepModeSP, nullptr);
844  return false;
845  }
846 
847  StepModeSP.s = IPS_OK;
848  IDSetSwitch(&StepModeSP, nullptr);
849  return true;
850  }
851 
852  if (strcmp(RotDirSP.name, name) == 0)
853  {
854  bool rc = false;
855  int current_mode = IUFindOnSwitchIndex(&RotDirSP);
856  IUUpdateSwitch(&RotDirSP, states, names, n);
857  int target_mode = IUFindOnSwitchIndex(&RotDirSP);
858  if (current_mode == target_mode)
859  {
860  RotDirSP.s = IPS_OK;
861  IDSetSwitch(&RotDirSP, nullptr);
862  return true;
863  }
864 
865  rc = setRotDir(target_mode);
866  if (!rc)
867  {
868  IUResetSwitch(&RotDirSP);
869  RotDirS[current_mode].s = ISS_ON;
870  RotDirSP.s = IPS_ALERT;
871  IDSetSwitch(&RotDirSP, nullptr);
872  return false;
873  }
874 
875  RotDirSP.s = IPS_OK;
876  IDSetSwitch(&RotDirSP, nullptr);
877  return true;
878  }
879 
880  if (strcmp(TemperatureCompensateSP.name, name) == 0)
881  {
882  int last_index = IUFindOnSwitchIndex(&TemperatureCompensateSP);
883  IUUpdateSwitch(&TemperatureCompensateSP, states, names, n);
884 
885  bool rc = setTemperatureCompensation((TemperatureCompensateS[0].s == ISS_ON));
886 
887  if (!rc)
888  {
889  TemperatureCompensateSP.s = IPS_ALERT;
890  IUResetSwitch(&TemperatureCompensateSP);
891  TemperatureCompensateS[last_index].s = ISS_ON;
892  IDSetSwitch(&TemperatureCompensateSP, nullptr);
893  return false;
894  }
895 
896  TemperatureCompensateSP.s = IPS_OK;
897  IDSetSwitch(&TemperatureCompensateSP, nullptr);
898  return true;
899  }
900 
901  if (strcmp(TempCompSignSP.name, name) == 0)
902  {
903  bool rc = false;
904  int current_mode = IUFindOnSwitchIndex(&TempCompSignSP);
905  IUUpdateSwitch(&TempCompSignSP, states, names, n);
906  int target_mode = IUFindOnSwitchIndex(&TempCompSignSP);
907  if (current_mode == target_mode)
908  {
909  TempCompSignSP.s = IPS_OK;
910  IDSetSwitch(&TempCompSignSP, nullptr);
911  return true;
912  }
913 
914  rc = setTempCompSign(target_mode);
915  if (!rc)
916  {
917  IUResetSwitch(&TempCompSignSP);
918  TempCompSignS[current_mode].s = ISS_ON;
919  TempCompSignSP.s = IPS_ALERT;
920  IDSetSwitch(&TempCompSignSP, nullptr);
921  return false;
922  }
923 
924  TempCompSignSP.s = IPS_OK;
925  IDSetSwitch(&TempCompSignSP, nullptr);
926  return true;
927  }
928 
929  // if (strcmp(BacklashDirectionSP.name, name) == 0)
930  // {
931  // IUUpdateSwitch(&BacklashDirectionSP, states, names, n);
932  // int target_direction = IUFindOnSwitchIndex(&BacklashDirectionSP);
933  // backlashIn = (target_direction == BACKLASH_IN);
934  // BacklashDirectionSP.s = IPS_OK;
935  // IDSetSwitch(&BacklashDirectionSP, nullptr);
936  // return true;
937  // }
938 
939  if (strcmp(ResetSP.name, name) == 0)
940  {
941  IUResetSwitch(&ResetSP);
942 
943  if (reset())
944  ResetSP.s = IPS_OK;
945  else
946  ResetSP.s = IPS_ALERT;
947 
948  IDSetSwitch(&ResetSP, nullptr);
949  return true;
950  }
951  }
952 
953  return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
954 }
955 
956 bool USBFocusV3::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
957 {
958  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
959  {
960  if (strcmp(name, MaxPositionNP.name) == 0)
961  {
962  IUUpdateNumber(&MaxPositionNP, values, names, n);
963  if (!setMaxPos(MaxPositionN[0].value))
964  {
965  MaxPositionNP.s = IPS_ALERT;
966  IDSetNumber(&MaxPositionNP, nullptr);
967  return false;
968  }
969  MaxPositionNP.s = IPS_OK;
970  IDSetNumber(&MaxPositionNP, nullptr);
971  return true;
972  }
973 
974  if (strcmp(name, TemperatureSettingNP.name) == 0)
975  {
976  IUUpdateNumber(&TemperatureSettingNP, values, names, n);
977  if (!setAutoTempCompThreshold(TemperatureSettingN[1].value) ||
978  !setTemperatureCoefficient(TemperatureSettingN[UFOPNSIGN].value))
979  {
980  TemperatureSettingNP.s = IPS_ALERT;
981  IDSetNumber(&TemperatureSettingNP, nullptr);
982  return false;
983  }
984 
985  TemperatureSettingNP.s = IPS_OK;
986  IDSetNumber(&TemperatureSettingNP, nullptr);
987  return true;
988  }
989 
990  // if (strcmp(name, BacklashSettingNP.name) == 0)
991  // {
992  // IUUpdateNumber(&BacklashSettingNP, values, names, n);
993  // backlashSteps = std::round(BacklashSettingN[0].value);
994  // BacklashSettingNP.s = IPS_OK;
995  // IDSetNumber(&BacklashSettingNP, nullptr);
996  // return true;
997  // }
998 
999  if (strcmp(name, FWversionNP.name) == 0)
1000  {
1001  IUUpdateNumber(&FWversionNP, values, names, n);
1002  FWversionNP.s = IPS_OK;
1003  IDSetNumber(&FWversionNP, nullptr);
1004  return true;
1005  }
1006  }
1007 
1008  return INDI::Focuser::ISNewNumber(dev, name, values, names, n);
1009 }
1010 
1011 void USBFocusV3::GetFocusParams()
1012 {
1014 
1015  if (updatePosition())
1016  IDSetNumber(&FocusAbsPosNP, nullptr);
1017 
1018  if (updateMaxPos())
1019  {
1020  IDSetNumber(&MaxPositionNP, nullptr);
1021  IDSetNumber(&FocusAbsPosNP, nullptr);
1022  }
1023 
1024  if (updateTemperature())
1025  IDSetNumber(&TemperatureNP, nullptr);
1026 
1027  if (updateTempCompSettings())
1028  IDSetNumber(&TemperatureSettingNP, nullptr);
1029 
1030  if (updateTempCompSign())
1031  IDSetSwitch(&TempCompSignSP, nullptr);
1032 
1033  if (updateSpeed())
1034  IDSetNumber(&FocusSpeedNP, nullptr);
1035 
1036  if (updateStepMode())
1037  IDSetSwitch(&StepModeSP, nullptr);
1038 
1039  if (updateRotDir())
1040  IDSetSwitch(&RotDirSP, nullptr);
1041 
1042  if (updateFWversion())
1043  IDSetNumber(&FWversionNP, nullptr);
1044 }
1045 
1047 {
1048  bool rc = false;
1049 
1050  rc = setSpeed(speed);
1051 
1052  if (!rc)
1053  return false;
1054 
1055  currentSpeed = speed;
1056 
1057  FocusSpeedNP.s = IPS_OK;
1058  IDSetNumber(&FocusSpeedNP, nullptr);
1059 
1060  return true;
1061 }
1062 
1064 {
1065  long ticks;
1066 
1067  targetPos = targetTicks;
1068 
1069  ticks = targetPos - FocusAbsPosN[0].value;
1070 
1071  bool rc = false;
1072 
1073  if (ticks < 0)
1074  rc = MoveFocuserUF(FOCUS_INWARD, -ticks);
1075  else if (ticks > 0)
1076  rc = MoveFocuserUF(FOCUS_OUTWARD, ticks);
1077 
1078  if (!rc)
1079  return IPS_ALERT;
1080 
1082 
1083  return IPS_BUSY;
1084 }
1085 
1087 {
1088  bool rc = false;
1089  uint32_t aticks;
1090 
1091  if ((dir == FOCUS_INWARD) && (ticks > FocusAbsPosN[0].value))
1092  {
1093  aticks = FocusAbsPosN[0].value;
1095  "Requested %u ticks but relative inward movement has been limited to %u ticks", ticks, aticks);
1096  ticks = aticks;
1097  }
1098  else if ((dir == FOCUS_OUTWARD) && ((FocusAbsPosN[0].value + ticks) > MaxPositionN[0].value))
1099  {
1100  aticks = MaxPositionN[0].value - FocusAbsPosN[0].value;
1102  "Requested %u ticks but relative outward movement has been limited to %u ticks", ticks, aticks);
1103  ticks = aticks;
1104  }
1105 
1106  rc = MoveFocuserUF(dir, (unsigned int)ticks);
1107 
1108  if (!rc)
1109  return IPS_ALERT;
1110 
1111  FocusRelPosN[0].value = ticks;
1113 
1114  return IPS_BUSY;
1115 }
1116 
1118 {
1119  if (!isConnected())
1120  {
1121  return;
1122  }
1123 
1124  bool rc = updatePosition();
1125 
1126  if (rc)
1127  {
1128  if (fabs(lastPos - FocusAbsPosN[0].value) > 5)
1129  {
1130  IDSetNumber(&FocusAbsPosNP, nullptr);
1131  lastPos = FocusAbsPosN[0].value;
1132  }
1133  }
1134 
1135  rc = updateTemperature();
1136 
1137  if (rc)
1138  {
1139  if (fabs(lastTemperature - TemperatureN[0].value) >= 0.5)
1140  {
1141  IDSetNumber(&TemperatureNP, nullptr);
1142  lastTemperature = TemperatureN[0].value;
1143  }
1144  }
1145 
1146  if (FocusTimerNP.s == IPS_BUSY)
1147  {
1148  float remaining = CalcTimeLeft(focusMoveStart, focusMoveRequest);
1149 
1150  if (remaining <= 0)
1151  {
1152  FocusTimerNP.s = IPS_OK;
1153  FocusTimerN[0].value = 0;
1154  AbortFocuser();
1155  }
1156  else
1157  FocusTimerN[0].value = remaining * 1000.0;
1158 
1159  IDSetNumber(&FocusTimerNP, nullptr);
1160  }
1161 
1163  {
1164  if (backlashMove && (fabs(backlashTargetPos - FocusAbsPosN[0].value) < 1))
1165  {
1166  // Backlash target reached, now go to real target
1167  MoveAbsFocuser(targetPos);
1168  backlashMove = false;
1169  }
1170  else
1171  {
1172  if (fabs(targetPos - FocusAbsPosN[0].value) < 1)
1173  {
1176  IDSetNumber(&FocusAbsPosNP, nullptr);
1177  IDSetNumber(&FocusRelPosNP, nullptr);
1178  lastPos = FocusAbsPosN[0].value;
1179  LOG_INFO("Focuser reached requested position.");
1180  }
1181  }
1182  }
1183 
1185 }
1186 
1188 {
1189  char resp[UFORESLEN] = {};
1190  if (!sendCommand(UFOCABORT, resp))
1191  return false;
1192 
1195  IDSetNumber(&FocusAbsPosNP, nullptr);
1196  IDSetNumber(&FocusRelPosNP, nullptr);
1197  backlashMove = false;
1198  moving = false;
1199  return true;
1200 }
1201 
1202 float USBFocusV3::CalcTimeLeft(timeval start, float req)
1203 {
1204  double timesince;
1205  double timeleft;
1206  struct timeval now
1207  {
1208  0, 0
1209  };
1210  gettimeofday(&now, nullptr);
1211 
1212  timesince =
1213  (double)(now.tv_sec * 1000.0 + now.tv_usec / 1000) - (double)(start.tv_sec * 1000.0 + start.tv_usec / 1000);
1214  timesince = timesince / 1000;
1215  timeleft = req - timesince;
1216  return timeleft;
1217 }
1218 
1220 {
1221  backlashIn = steps < 0;
1222  backlashSteps = std::abs(steps);
1223 
1224  return true;
1225 }
1226 
1227 //bool USBFocusV3::saveConfigItems(FILE *fp)
1228 //{
1229 // INDI::Focuser::saveConfigItems(fp);
1230 
1231 // IUSaveConfigNumber(fp, &BacklashSettingNP);
1232 // IUSaveConfigSwitch(fp, &BacklashDirectionSP);
1233 // return true;
1234 //}
UFOCSETHSTEPS
#define UFOCSETHSTEPS
Definition: usbfocusv3.h:41
INDI::FocuserInterface::FOCUSER_CAN_ABS_MOVE
@ FOCUSER_CAN_ABS_MOVE
Definition: indifocuserinterface.h:74
IP_RO
@ IP_RO
Definition: indiapi.h:183
INDI::FocuserInterface::FOCUSER_CAN_REL_MOVE
@ FOCUSER_CAN_REL_MOVE
Definition: indifocuserinterface.h:75
INDI::FocuserInterface::FocusAbsPosNP
INumberVectorProperty FocusAbsPosNP
Definition: indifocuserinterface.h:282
cmd
__u8 cmd[4]
Definition: pwc-ioctl.h:4
USBFocusV3::SetFocuserBacklash
virtual bool SetFocuserBacklash(int32_t steps) override
SetFocuserBacklash Set the focuser backlash compensation value.
Definition: usbfocusv3.cpp:1219
UFORSDONE
#define UFORSDONE
Definition: usbfocusv3.h:55
UFOCGETSIGN
#define UFOCGETSIGN
Definition: usbfocusv3.h:43
UFOCSETSPEED
#define UFOCSETSPEED
Definition: usbfocusv3.h:36
IPState
IPState
Property state.
Definition: indiapi.h:158
tty_nread_section
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
Definition: indicom.c:657
UFOCREADTEMP
#define UFOCREADTEMP
Definition: usbfocusv3.h:31
INDI::FocuserInterface::FocusBacklashN
INumber FocusBacklashN[1]
Definition: indifocuserinterface.h:311
LOGF_ERROR
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
USBFocusV3::MoveRelFocuser
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
Definition: usbfocusv3.cpp:1086
ISS_OFF
@ ISS_OFF
Definition: indiapi.h:150
indicom.h
Implementations for common driver routines.
UFORESLEN
#define UFORESLEN
Definition: usbfocusv3.h:71
INDI::Logger::DBG_WARNING
@ DBG_WARNING
Definition: indilogger.h:193
UFOPFSTEPS
#define UFOPFSTEPS
Definition: usbfocusv3.h:61
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
USBFocusV3::Handshake
virtual bool Handshake() override
perform handshake with device to check communication
Definition: usbfocusv3.cpp:196
IUFillNumber
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.
Definition: indidriver.c:348
INDI::DefaultDevice::defineProperty
void defineProperty(INumberVectorProperty *property)
Definition: defaultdevice.cpp:997
OPTIONS_TAB
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
Definition: defaultdevice.cpp:39
MAIN_CONTROL_TAB
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
Definition: defaultdevice.cpp:34
INDI::FocuserInterface::FocusTimerN
INumber FocusTimerN[1]
Definition: indifocuserinterface.h:279
UFOPHSTEPS
#define UFOPHSTEPS
Definition: usbfocusv3.h:62
INDI::DefaultDevice::setDefaultPollingPeriod
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
Definition: defaultdevice.cpp:1157
UFORSACK
#define UFORSACK
Definition: usbfocusv3.h:53
INDI::FocuserInterface::FOCUSER_HAS_VARIABLE_SPEED
@ FOCUSER_HAS_VARIABLE_SPEED
Definition: indifocuserinterface.h:79
UFOCSETSTDEG
#define UFOCSETSTDEG
Definition: usbfocusv3.h:42
USBFocusV3::TimerHit
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition: usbfocusv3.cpp:1117
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
USBFocusV3::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: usbfocusv3.cpp:49
INDI::FocuserInterface::FOCUSER_CAN_ABORT
@ FOCUSER_CAN_ABORT
Definition: indifocuserinterface.h:76
LOG_INFO
#define LOG_INFO(txt)
Definition: indilogger.h:74
MAXRBUF
#define MAXRBUF
Definition: indidriver.c:52
UFOCRESET
#define UFOCRESET
Definition: usbfocusv3.h:47
UFOCSETSDIR
#define UFOCSETSDIR
Definition: usbfocusv3.h:38
IUResetSwitch
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indicom.c:1442
tty_error_msg
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1156
UFOCREADPARAM
#define UFOCREADPARAM
Definition: usbfocusv3.h:28
INDI::DefaultDevice::getCurrentPollingPeriod
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
Definition: defaultdevice.cpp:1139
USBFocusV3::FOCUS_FULL_STEP
@ FOCUS_FULL_STEP
Definition: usbfocusv3.h:85
tty_read
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition: indicom.c:473
UFOPSPDAV
#define UFOPSPDAV
Definition: usbfocusv3.h:67
LOGF_DEBUG
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
USBFocusV3
Definition: usbfocusv3.h:76
UFOCSETMAX
#define UFOCSETMAX
Definition: usbfocusv3.h:35
INDI::DefaultDevice::SetTimer
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
Definition: defaultdevice.cpp:865
INDI::Focuser::PortFD
int PortFD
Definition: indifocuser.h:116
UFOID
#define UFOID
Definition: usbfocusv3.h:51
INDI::FocuserInterface::FocusTimerNP
INumberVectorProperty FocusTimerNP
Definition: indifocuserinterface.h:278
tty_write
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition: indicom.c:415
LOGF_WARN
#define LOGF_WARN(fmt,...)
Definition: indilogger.h:81
INDI::FocuserInterface::FOCUS_INWARD
@ FOCUS_INWARD
Definition: indifocuserinterface.h:68
IUFillSwitchVector
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.
Definition: indidriver.c:412
IUFillNumberVector
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.
Definition: indidriver.c:455
IPS_BUSY
@ IPS_BUSY
Definition: indiapi.h:162
ISR_1OFMANY
@ ISR_1OFMANY
Definition: indiapi.h:172
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
INDI::FocuserInterface::FocusRelPosN
INumber FocusRelPosN[1]
Definition: indifocuserinterface.h:287
INDI::Focuser::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: indifocuser.cpp:120
_INumberVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:322
INDI::DefaultDevice::loadConfig
virtual bool loadConfig(bool silent=false, const char *property=nullptr)
Load the last saved configuration file.
Definition: defaultdevice.cpp:147
IUUpdateSwitch
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:171
INDI::FocuserInterface::FocusRelPosNP
INumberVectorProperty FocusRelPosNP
Definition: indifocuserinterface.h:286
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
UFOCSETFSTEPS
#define UFOCSETFSTEPS
Definition: usbfocusv3.h:40
UFOPSPDUS
#define UFOPSPDUS
Definition: usbfocusv3.h:69
UFOCDEVID
#define UFOCDEVID
Definition: usbfocusv3.h:29
USBFocusV3::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: usbfocusv3.cpp:956
LOGF_INFO
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
USBFocusV3::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: usbfocusv3.cpp:816
LOG_ERROR
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition: indilogger.h:72
INDI::FocuserInterface::SetCapability
void SetCapability(uint32_t cap)
FI::SetCapability sets the focuser capabilities. All capabilities must be initialized.
Definition: indifocuserinterface.h:95
USBFocusV3::FOCUS_HALF_STEP
@ FOCUS_HALF_STEP
Definition: usbfocusv3.h:84
UFOPSPDSL
#define UFOPSPDSL
Definition: usbfocusv3.h:68
name
const char * name
Definition: indiserver.c:116
UFOCSETTCTHR
#define UFOCSETTCTHR
Definition: usbfocusv3.h:37
_ISwitchVectorProperty::s
IPState s
Definition: indiapi.h:382
UFOPSDIR
#define UFOPSDIR
Definition: usbfocusv3.h:59
UFOCMDLEN
#define UFOCMDLEN
Definition: usbfocusv3.h:72
UFOCMOVEOUT
#define UFOCMOVEOUT
Definition: usbfocusv3.h:32
USBFOCUSV3_TIMEOUT
#define USBFOCUSV3_TIMEOUT
Definition: usbfocusv3.cpp:33
UFOPRDIR
#define UFOPRDIR
Definition: usbfocusv3.h:60
IUUpdateNumber
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:225
USBFocusV3::MoveAbsFocuser
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
Definition: usbfocusv3.cpp:1063
DEBUGF
#define DEBUGF(priority, msg,...)
Definition: indilogger.h:57
USBFocusV3::getDefaultName
virtual const char * getDefaultName() override
Definition: usbfocusv3.cpp:216
INDI::FocuserInterface::FocusDirection
FocusDirection
Definition: indifocuserinterface.h:66
IP_RW
@ IP_RW
Definition: indiapi.h:185
UFOPSPDERR
#define UFOPSPDERR
Definition: usbfocusv3.h:66
INDI::FocuserInterface::FocusSpeedNP
INumberVectorProperty FocusSpeedNP
Definition: indifocuserinterface.h:268
UFOCABORT
#define UFOCABORT
Definition: usbfocusv3.h:34
INDI::FocuserInterface::FOCUSER_HAS_BACKLASH
@ FOCUSER_HAS_BACKLASH
Definition: indifocuserinterface.h:80
USBFocusV3::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: usbfocusv3.cpp:153
ISState
ISState
Switch state.
Definition: indiapi.h:148
UFOPPSIGN
#define UFOPPSIGN
Definition: usbfocusv3.h:63
UFOCSETAUTO
#define UFOCSETAUTO
Definition: usbfocusv3.h:45
UFOCSETSIGN
#define UFOCSETSIGN
Definition: usbfocusv3.h:44
UFOPNSIGN
#define UFOPNSIGN
Definition: usbfocusv3.h:64
USBFocusV3::SetFocuserSpeed
virtual bool SetFocuserSpeed(int speed) override
SetFocuserSpeed Set Focuser speed.
Definition: usbfocusv3.cpp:1046
IUFindOnSwitchIndex
int IUFindOnSwitchIndex(const ISwitchVectorProperty *sp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indicom.c:1424
INDI::DefaultDevice::addDebugControl
void addDebugControl()
Add Debug control to the driver.
Definition: defaultdevice.cpp:639
UFOCREADPOS
#define UFOCREADPOS
Definition: usbfocusv3.h:30
INDI::Focuser::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indifocuser.cpp:58
TTY_OK
@ TTY_OK
Definition: indicom.h:94
usbfocusv3.h
INDI::DefaultDevice::deleteProperty
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
Definition: defaultdevice.cpp:965
INDI::Focuser::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: indifocuser.cpp:168
INDI::FocuserInterface::FocusAbsPosN
INumber FocusAbsPosN[1]
Definition: indifocuserinterface.h:283
IDSetNumber
void void void IDSetNumber(const INumberVectorProperty *n, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing number vector property.
IDSetSwitch
void void void void void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing switch vector property.
USBFocusV3::getControllerStatus
bool getControllerStatus()
Definition: usbfocusv3.cpp:366
USBFocusV3::USBFocusV3
USBFocusV3()
Definition: usbfocusv3.cpp:39
IUFillSwitch
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.
Definition: indidriver.c:320
UFOCSETMANU
#define UFOCSETMANU
Definition: usbfocusv3.h:46
USBFocusV3::AbortFocuser
virtual bool AbortFocuser() override
AbortFocuser all focus motion.
Definition: usbfocusv3.cpp:1187
INDI::Focuser::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: indifocuser.cpp:145
UFOCSETRDIR
#define UFOCSETRDIR
Definition: usbfocusv3.h:39
INDI::FocuserInterface::FocusSpeedN
INumber FocusSpeedN[1]
Definition: indifocuserinterface.h:269
UFOCMOVEIN
#define UFOCMOVEIN
Definition: usbfocusv3.h:33
_ISwitchVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:370
ISS_ON
@ ISS_ON
Definition: indiapi.h:151
INDI::FocuserInterface::FOCUS_OUTWARD
@ FOCUS_OUTWARD
Definition: indifocuserinterface.h:69