Instrument Neutral Distributed Interface INDI  1.9.5
tcfs.cpp
Go to the documentation of this file.
1 /*
2  INDI Driver for Optec TCF-S Focuser
3 
4  Copyright (C) 2010 Jasem Mutlaq (mutlaqja@ikarustech.com)
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 "tcfs.h"
23 
24 #include "indicom.h"
26 
27 #include <cmath>
28 #include <memory>
29 #include <cstring>
30 #include <termios.h>
31 
32 #define mydev "Optec TCF-S"
33 #define currentPosition FocusAbsPosN[0].value
34 
35 // We declare an auto pointer to TCFS.
36 static std::unique_ptr<TCFS> tcfs(new TCFS());
37 
38 /****************************************************************
39 **
40 **
41 *****************************************************************/
43 {
44  currentMode = MANUAL;
46 
47  setVersion(0, 4);
48 }
49 
50 /****************************************************************
51 **
52 **
53 *****************************************************************/
55 {
56  //LOGF_DEBUG("%s %s",__FUNCTION__, me);
58 
59  // Set upper limit for TCF-S3 focuser
60  if (strcmp(me, "indi_tcfs3_focus") == 0)
61  {
62  isTCFS3 = true;
63 
64  FocusMaxPosN[0].max = 9999;
65  FocusAbsPosN[0].max = 9999;
66  FocusRelPosN[0].max = 2000;
67  FocusRelPosN[0].step = 100;
68  FocusAbsPosN[0].step = 100;
69  FocusRelPosN[0].value = 0;
70  LOG_DEBUG("TCF-S3 detected. Updating maximum position value to 9999.");
71  }
72  else
73  {
74  isTCFS3 = false;
75 
76  FocusMaxPosN[0].max = 7000;
77  FocusAbsPosN[0].max = 7000;
78  FocusRelPosN[0].max = 2000;
79  FocusRelPosN[0].step = 100;
80  FocusAbsPosN[0].step = 100;
81  FocusRelPosN[0].value = 0;
82  LOG_DEBUG("TCF-S detected. Updating maximum position value to 7000.");
83  }
84 
85  IUFillSwitch(&FocusModeS[0], "Manual", "", ISS_ON);
86  IUFillSwitch(&FocusModeS[1], "Auto A", "", ISS_OFF);
87  IUFillSwitch(&FocusModeS[2], "Auto B", "", ISS_OFF);
88  IUFillSwitchVector(&FocusModeSP, FocusModeS, 3, getDeviceName(), "FOCUS_MODE", "Mode", "Main Control", IP_RW,
89  ISR_1OFMANY, 0, IPS_IDLE);
90 
91  IUFillSwitch(&FocusPowerS[0], "FOCUS_SLEEP", "Sleep", ISS_OFF);
92  IUFillSwitch(&FocusPowerS[1], "FOCUS_WAKEUP", "Wake up", ISS_OFF);
93  IUFillSwitchVector(&FocusPowerSP, FocusPowerS, 2, getDeviceName(), "FOCUS_POWER", "Power", "Operation", IP_RW,
94  ISR_ATMOST1, 0, IPS_IDLE);
95 
96  IUFillSwitch(&FocusGotoS[0], "FOCUS_MIN", "Min", ISS_OFF);
97  IUFillSwitch(&FocusGotoS[1], "FOCUS_CENTER", "Center", ISS_OFF);
98  IUFillSwitch(&FocusGotoS[2], "FOCUS_MAX", "Max", ISS_OFF);
99  IUFillSwitch(&FocusGotoS[3], "FOCUS_HOME", "Home", ISS_OFF);
100  IUFillSwitchVector(&FocusGotoSP, FocusGotoS, 4, getDeviceName(), "FOCUS_GOTO", "Go to", "Main Control", IP_RW,
101  ISR_ATMOST1, 0, IPS_IDLE);
102 
103  IUFillNumber(&FocusTemperatureN[0], "FOCUS_TEMPERATURE_VALUE", "Temperature (c)", "%.3f", -50.0, 80, 0, 0);
104  IUFillNumberVector(&FocusTemperatureNP, FocusTemperatureN, 1, getDeviceName(), "FOCUS_TEMPERATURE", "Probe", "Operation", IP_RO, 0, IPS_IDLE);
105 
106  IUFillSwitch(&FocusTelemetryS[0], "FOCUS_TELEMETRY_ON", "Enable", ISS_ON);
107  IUFillSwitch(&FocusTelemetryS[1], "FOCUS_TELEMETRY_OFF", "Disable", ISS_OFF);
108  IUFillSwitchVector(&FocusTelemetrySP, FocusTelemetryS, 2, getDeviceName(), "FOCUS_TELEMETRY", "Telemetry", "Operation", IP_RW,
109  ISR_1OFMANY, 0, IPS_IDLE);
110 
111  // Mode parameters
112  IUFillNumber(&FocusModeAN[0], "FOCUS_SLOPE_A", "Slope A", "%.0f", -999, 999, 10, 0);
113  IUFillNumber(&FocusModeAN[1], "FOCUS_INTERCEPT_A", "Intercept A", "%.0f", 0, FocusAbsPosN[0].max, 10, 0);
114  IUFillNumber(&FocusModeAN[2], "FOCUS_DELAY_A", "Delay A", "%.2f", 0.00, 9.99, 1.0, 0);
115  IUFillNumberVector(&FocusModeANP, FocusModeAN, 3, getDeviceName(), "FOCUS_MODE_A", "Mode A", "Presets", IP_RW, 0, IPS_IDLE);
116  IUFillNumber(&FocusModeBN[0], "FOCUS_SLOPE_B", "Slope B", "%.0f", -999, 999, 10, 0);
117  IUFillNumber(&FocusModeBN[1], "FOCUS_INTERCEPT_B", "Intercept B", "%.0f", 0, FocusAbsPosN[0].max, 10, 0);
118  IUFillNumber(&FocusModeBN[2], "FOCUS_DELAY_B", "Delay B", "%.2f", 0.00, 9.99, 1.0, 0);
119  IUFillNumberVector(&FocusModeBNP, FocusModeBN, 3, getDeviceName(), "FOCUS_MODE_B", "Mode B", "Presets", IP_RW, 0, IPS_IDLE);
120 
121  IUFillSwitch(&FocusStartModeS[0], "FOCUS_START_ON", "Enable", ISS_OFF);
122  IUFillSwitch(&FocusStartModeS[1], "FOCUS_START_OFF", "Disable", ISS_ON);
123  IUFillSwitchVector(&FocusStartModeSP, FocusStartModeS, 2, getDeviceName(), "FOCUS_START_MODE", "Startup Mode", "Presets", IP_RW,
124  ISR_1OFMANY, 0, IPS_IDLE);
125 
126  // Default to 19200
128 
129  addAuxControls();
130 
132 
133  return true;
134 }
135 
136 /****************************************************************
137 **
138 **
139 *****************************************************************/
141 {
142  //LOGF_DEBUG("%s %s",__FUNCTION__, me);
144 
145  if (isConnected())
146  {
147  defineProperty(&FocusGotoSP);
148  defineProperty(&FocusTemperatureNP);
149  defineProperty(&FocusPowerSP);
150  defineProperty(&FocusModeSP);
151  defineProperty(&FocusTelemetrySP);
152  defineProperty(&FocusStartModeSP);
153  defineProperty(&FocusModeANP);
154  defineProperty(&FocusModeBNP);;
155  GetFocusParams();
156  }
157  else
158  {
159  deleteProperty(FocusGotoSP.name);
160  deleteProperty(FocusTemperatureNP.name);
161  deleteProperty(FocusPowerSP.name);
162  deleteProperty(FocusModeSP.name);
163  deleteProperty(FocusTelemetrySP.name);
164  deleteProperty(FocusStartModeSP.name);
165  deleteProperty(FocusModeANP.name);
166  deleteProperty(FocusModeBNP.name);;
167  }
168 
169  return true;
170 }
171 
172 /****************************************************************
173 **
174 **
175 *****************************************************************/
176 bool TCFS::saveConfigItems(FILE *fp)
177 {
179 
180  IUSaveConfigNumber(fp, &FocusModeANP);
181  IUSaveConfigNumber(fp, &FocusModeBNP);
182  IUSaveConfigSwitch(fp, &FocusStartModeSP);
183 
184  // Add more properties to config file here
185  // IUSaveConfigSwitch(fp, &SwitchSP);
186  // IUSaveConfigNumber(fp, &NumberNP);
187  // IUSaveConfigText(fp, &TextTP);
188 
189  return true;
190 }
191 
192 /****************************************************************
193 **
194 **
195 *****************************************************************/
197 {
198  LOGF_DEBUG("A slope=%.0f", FocusModeANP.np[0].value);//, FocusModeAN[0].value);
199  /*
200  char response[TCFS_MAX_CMD] = { 0 };
201  int slope;
202  int is_negative;
203  dispatch_command(FRSLOP, 0, MODE_A);
204  read_tcfs(response);
205  if(sscanf(response, "A=%04d", &slope)<=0)
206  {
207  LOGF_WARN("Failed to read slope A from response: %s", response);
208  return;
209  }
210  response[0] = '\0';
211  dispatch_command(FRSIGN, 0, MODE_A);
212  read_tcfs(response);
213  if(sscanf(response, "A=%01d", &is_negative)<=0)
214  {
215  LOGF_WARN("Failed to read slope sign A from response: %s", response);
216  return;
217  }
218 
219  FocusModeANP.np[0].value = slope * (is_negative==1?-1:1);
220  IDSetNumber(&FocusModeANP, nullptr);
221 
222  response[0] = '\0';
223  dispatch_command(FRSLOP, 0, MODE_B);
224  read_tcfs(response);
225  if(sscanf(response, "B=%04d", &slope)<=0)
226  {
227  LOGF_WARN("Failed to read slope B from response: %s", response);
228  return;
229  }
230 
231  response[0] = '\0';
232  dispatch_command(FRSIGN, 0, MODE_B);
233  read_tcfs(response);
234  if(sscanf(response, "B=%01d", &is_negative)<=0)
235  {
236  LOGF_WARN("Failed to read slope sign B from response: %s", response);
237  return;
238  }
239 
240  FocusModeBNP.np[0].value = slope * (is_negative==1?-1:1);
241  IDSetNumber(&FocusModeBNP, nullptr);
242  */
243 }
244 
245 /****************************************************************
246 **
247 **
248 *****************************************************************/
250 {
251  LOGF_DEBUG("%s %s", __FUNCTION__, me);
252  if (isSimulation())
253  {
254  LOG_INFO("TCF-S: Simulating connection.");
255  currentPosition = simulated_position;
256  return true;
257  }
258  char response[TCFS_MAX_CMD] = { 0 };
259  dispatch_command(FWAKUP);
260  read_tcfs(response);
261  if (strcmp(response, "WAKE") == 0)
262  {
263  LOG_INFO("TCF-S Focuser is awake");
264  tcflush(PortFD, TCIOFLUSH);
265  }
266 
267  if(SetManualMode())
268  {
269  LOG_INFO("Successfully connected to TCF-S Focuser in Manual Mode.");
270 
271  // Enable temperature readout
272  FocusTemperatureNP.s = IPS_OK;
273 
274  return true;
275  }
276  tcflush(PortFD, TCIOFLUSH);
277  LOG_ERROR("Failed connection to TCF-S Focuser.");
278  return false;
279 }
280 /****************************************************************
281 **
282 **
283 *****************************************************************/
285 {
286  char response[TCFS_MAX_CMD] = { 0 };
287  for(int retry = 0; retry < 5; retry++)
288  {
289  dispatch_command(FMMODE);
290  read_tcfs(response);
291  if (strcmp(response, "!") == 0)
292  {
293  tcflush(PortFD, TCIOFLUSH);
294  currentMode = MANUAL;
295  return true;
296  }
297  }
298  tcflush(PortFD, TCIOFLUSH);
299  return false;
300 }
301 
302 /****************************************************************
303 **
304 **
305 *****************************************************************/
307 {
308  FocusTemperatureNP.s = IPS_IDLE;
309  IDSetNumber(&FocusTemperatureNP, nullptr);
310 
311  dispatch_command(FFMODE);
312 
313  return INDI::Focuser::Disconnect();
314 }
315 
316 /****************************************************************
317 **
318 **
319 *****************************************************************/
320 bool TCFS::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
321 {
322  //LOGF_DEBUG("%s %s %s %s",__FUNCTION__, me, dev, name);
323  // first check if it's for our device
324  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
325  {
326  char response[TCFS_MAX_CMD] = { 0 };
327  // In Auto mode only FMMODE can be accepted
328  // In Sleep mode only FWAKUP can be accepted
329  // While focuser is moving don't allow actions other than FMMODE
330 
331  if (!strcmp(name, FocusModeANP.name))
332  {
333  IUUpdateNumber(&FocusModeANP, values, names, n);
334 
335  dispatch_command(FLSLOP, FocusModeAN[0].value, MODE_A);
336  if (read_tcfs(response) == false)
337  {
338  FocusModeANP.s = IPS_ALERT;
339  IDSetNumber(&FocusModeANP, "Error reading TCF-S reply.");
340  return true;
341  }
342  dispatch_command(FLSIGN, FocusModeAN[0].value, MODE_A);
343  if (read_tcfs(response) == false)
344  {
345  FocusModeANP.s = IPS_ALERT;
346  IDSetNumber(&FocusModeANP, "Error reading TCF-S reply.");
347  return true;
348  }
349  //saveConfig();
350  dispatch_command(FDELAY, FocusModeAN[2].value * 100, MODE_A);
351  if (read_tcfs(response) == false)
352  {
353  FocusModeANP.s = IPS_ALERT;
354  IDSetNumber(&FocusModeANP, "Error reading TCF-S reply.");
355  return true;
356  }
357  //saveConfig();
358  FocusModeANP.s = IPS_OK;
359  IDSetNumber(&FocusModeANP, nullptr);
360 
361  return true;
362  }
363  if (!strcmp(name, FocusModeBNP.name))
364  {
365  IUUpdateNumber(&FocusModeBNP, values, names, n);
366 
367  dispatch_command(FLSLOP, FocusModeBN[0].value, MODE_B);
368  if (read_tcfs(response) == false)
369  {
370  FocusModeBNP.s = IPS_ALERT;
371  IDSetNumber(&FocusModeBNP, "Error reading TCF-S reply.");
372  return true;
373  }
374  dispatch_command(FLSIGN, FocusModeBN[0].value, MODE_B);
375  if (read_tcfs(response) == false)
376  {
377  FocusModeBNP.s = IPS_ALERT;
378  IDSetNumber(&FocusModeBNP, "Error reading TCF-S reply.");
379  return true;
380  }
381  dispatch_command(FDELAY, FocusModeBN[2].value * 100, MODE_B);
382  if (read_tcfs(response) == false)
383  {
384  FocusModeBNP.s = IPS_ALERT;
385  IDSetNumber(&FocusModeBNP, "Error reading TCF-S reply.");
386  return true;
387  }
388  //saveConfig();
389  FocusModeBNP.s = IPS_OK;
390  IDSetNumber(&FocusModeBNP, nullptr);
391 
392  return true;
393  }
394  }
395 
396  return Focuser::ISNewNumber(dev, name, values, names, n);
397 }
398 
399 /****************************************************************
400 **
401 **
402 *****************************************************************/
403 bool TCFS::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
404 {
405  //LOGF_DEBUG("%s %s %s %s",__FUNCTION__, me, dev, name);
406  if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
407  {
408  char response[TCFS_MAX_CMD] = { 0 };
409  // In Auto mode only FMMODE can be accepted
410  // In Sleep mode only FWAKUP can be accepted
411  // While focuser is moving don't allow actions other than FMMODE
412  if (!strcmp(FocusMotionSP.name, name))
413  {
414  if (FocusModeSP.sp[0].s != ISS_ON)
415  {
416  LOG_WARN("The focuser can only be moved in Manual mode.");
417  return true;
418  }
419  }
420  if (FocusRelPosNP.s == IPS_BUSY)
421  {
422  LOG_WARN("The focuser is in motion. Wait until it has stopped");
423  return true;
424  }
425  if (!strcmp(FocusPowerSP.name, name))
426  {
427  IUUpdateSwitch(&FocusPowerSP, states, names, n);
428  bool sleep = false;
429 
430  ISwitch *sp = IUFindOnSwitch(&FocusPowerSP);
431 
432  // Sleep
433  if (!strcmp(sp->name, "FOCUS_SLEEP"))
434  {
435  dispatch_command(FSLEEP);
436  sleep = true;
437  }
438  // Wake Up
439  else
440  dispatch_command(FWAKUP);
441 
442  if (read_tcfs(response) == false)
443  {
444  IUResetSwitch(&FocusPowerSP);
445  FocusPowerSP.s = IPS_ALERT;
446  IDSetSwitch(&FocusPowerSP, "Error reading TCF-S reply.");
447  return true;
448  }
449 
450  if (sleep)
451  {
452  if (isSimulation())
453  strncpy(response, "ZZZ", TCFS_MAX_CMD);
454 
455  if (strcmp(response, "ZZZ") == 0)
456  {
457  FocusPowerSP.s = IPS_OK;
458  IDSetSwitch(&FocusPowerSP, "Focuser is set into sleep mode.");
460  IDSetNumber(&FocusAbsPosNP, nullptr);
461  // if (FocusTemperatureNP)
462  {
463  FocusTemperatureNP.s = IPS_IDLE;
464  IDSetNumber(&FocusTemperatureNP, nullptr);
465  }
466 
467  return true;
468  }
469  else
470  {
471  FocusPowerSP.s = IPS_ALERT;
472  IDSetSwitch(&FocusPowerSP, "Focuser sleep mode operation failed. Response: %s.", response);
473  return true;
474  }
475  }
476  else
477  {
478  if (isSimulation())
479  strncpy(response, "WAKE", TCFS_MAX_CMD);
480 
481  if (strcmp(response, "WAKE") == 0)
482  {
483  FocusPowerSP.s = IPS_OK;
484  IDSetSwitch(&FocusPowerSP, "Focuser is awake.");
486  IDSetNumber(&FocusAbsPosNP, nullptr);
487  // if (FocusTemperatureNP)
488  {
489  FocusTemperatureNP.s = IPS_OK;
490  IDSetNumber(&FocusTemperatureNP, nullptr);
491  }
492 
493  return true;
494  }
495  else
496  {
497  FocusPowerSP.s = IPS_ALERT;
498  IDSetSwitch(&FocusPowerSP, "Focuser wake up operation failed. Response: %s", response);
499  return true;
500  }
501  }
502  }
503 
504  // Do not process any command if focuser is asleep
505  if (isConnected() && FocusPowerSP.sp[0].s == ISS_ON)
506  {
508  if (svp)
509  {
510  svp->s = IPS_IDLE;
511  LOG_WARN("Focuser is still in sleep mode. Wake up in order to issue commands.");
512  IDSetSwitch(svp, nullptr);
513  }
514  return true;
515  }
516 
517  if (!strcmp(FocusModeSP.name, name))
518  {
519  IUUpdateSwitch(&FocusModeSP, states, names, n);
520  FocusModeSP.s = IPS_OK;
521 
522  ISwitch *sp = IUFindOnSwitch(&FocusModeSP);
523 
524  if (!strcmp(sp->name, "Manual"))
525  {
526  if (!isSimulation() && !SetManualMode())
527  {
528  IUResetSwitch(&FocusModeSP);
529  FocusModeSP.s = IPS_ALERT;
530  IDSetSwitch(&FocusModeSP, "Error switching to manual mode. No reply from TCF-S. Try again.");
531  return true;
532  }
533  LOG_INFO("Entered Manual Mode");
534  currentMode = MANUAL;
535  }
536  else if (!strcmp(sp->name, "Auto A"))
537  {
538  if(FocusStartModeSP.sp[0].s == ISS_ON)
539  {
540  FocusModeSP.s = IPS_BUSY;
541  uint32_t startPos = -FocusTemperatureN[0].value * FocusModeAN[0].value
542  + FocusModeAN[1].value;
543  LOGF_DEBUG("Autocomp A T=%.1f; m=%f; i=%f; p0=%d;",
544  FocusTemperatureN[0].value,
545  FocusModeAN[0].value,
546  FocusModeAN[1].value,
547  startPos);
548  MoveAbsFocuser(startPos);
549  }
550  else
551  {
552  dispatch_command(FAMODE);
553  read_tcfs(response);
554  if (!isSimulation() && strcmp(response, "A") != 0)
555  {
556  IUResetSwitch(&FocusModeSP);
557  FocusModeSP.s = IPS_ALERT;
558  IDSetSwitch(&FocusModeSP, "Error switching to Auto Mode A, No reply from TCF-S. Try again.");
559  }
560  LOG_INFO("Entered Auto Mode A");
561  currentMode = MODE_A;
562  }
563  }
564  else
565  {
566  if(FocusStartModeSP.sp[0].s == ISS_ON)
567  {
568  FocusModeSP.s = IPS_BUSY;
569  uint32_t startPos = -FocusTemperatureN[0].value * FocusModeBN[0].value
570  + FocusModeBN[1].value;
571  LOGF_DEBUG("Autocomp B T=%.1f; m=%f; i=%f; p0=%d;",
572  FocusTemperatureN[0].value,
573  FocusModeBN[0].value,
574  FocusModeBN[1].value,
575  startPos);
576  MoveAbsFocuser(startPos);
577  }
578  else
579  {
580  dispatch_command(FBMODE);
581  read_tcfs(response);
582  if (!isSimulation() && strcmp(response, "B") != 0)
583  {
584  IUResetSwitch(&FocusModeSP);
585  FocusModeSP.s = IPS_ALERT;
586  IDSetSwitch(&FocusModeSP, "Error switching to Auto Mode B, No reply from TCF-S. Try again.");
587  }
588  LOG_INFO("Entered Auto Mode B");
589  currentMode = MODE_B;
590  }
591  }
592 
593  IDSetSwitch(&FocusModeSP, nullptr);
594  return true;
595  }
596  // Do not process any other command if focuser is in auto mode
597  if (isConnected() && FocusModeSP.sp[0].s != ISS_ON)
598  {
600  if (svp)
601  {
602  svp->s = IPS_IDLE;
603  LOG_WARN("Focuser is in auto mode. Change to manual in order to issue commands.");
604  IDSetSwitch(svp, nullptr);
605  }
606  return true;
607  }
608 
609  if (!strcmp(FocusStartModeSP.name, name))
610  {
611  IUUpdateSwitch(&FocusStartModeSP, states, names, n);
612  FocusStartModeSP.s = IPS_OK;
613  // ISwitch *sp = IUFindOnSwitch(&FocusStartModeSP);
614  IDSetSwitch(&FocusStartModeSP, nullptr);
615  LOGF_DEBUG("Start Mode %d", FocusStartModeSP.sp[0].s );
616  return true;
617  }
618 
619  if (!strcmp(FocusGotoSP.name, name))
620  {
621  if (FocusModeSP.sp[0].s != ISS_ON)
622  {
623  FocusGotoSP.s = IPS_IDLE;
624  IDSetSwitch(&FocusGotoSP, nullptr);
625  LOG_WARN("The focuser can only be moved in Manual mode.");
626  return false;
627  }
628 
629  IUUpdateSwitch(&FocusGotoSP, states, names, n);
630  FocusGotoSP.s = IPS_BUSY;
631 
632  ISwitch *sp = IUFindOnSwitch(&FocusGotoSP);
633 
634  // Min
635  if (!strcmp(sp->name, "FOCUS_MIN"))
636  {
637  targetTicks = currentPosition;
639  IDSetSwitch(&FocusGotoSP, "Moving focuser to minimum position...");
640  }
641  // Center
642  else if (!strcmp(sp->name, "FOCUS_CENTER"))
643  {
644  dispatch_command(FCENTR);
647  IDSetNumber(&FocusAbsPosNP, nullptr);
648  IDSetNumber(&FocusRelPosNP, nullptr);
649  IDSetSwitch(&FocusGotoSP, "Moving focuser to center position %d...", isTCFS3 ? 5000 : 3500);
650  return true;
651  }
652  // Max
653  else if (!strcmp(sp->name, "FOCUS_MAX"))
654  {
655  unsigned int delta = 0;
656  delta = FocusAbsPosN[0].max - currentPosition;
658  IDSetSwitch(&FocusGotoSP, "Moving focuser to maximum position %g...", FocusAbsPosN[0].max);
659  }
660  // Home
661  else if (!strcmp(sp->name, "FOCUS_HOME"))
662  {
663  dispatch_command(FHOME);
664  read_tcfs(response);
665 
666  if (isSimulation())
667  strncpy(response, "DONE", TCFS_MAX_CMD);
668 
669  if (strcmp(response, "DONE") == 0)
670  {
671  IUResetSwitch(&FocusGotoSP);
672  FocusGotoSP.s = IPS_OK;
673  IDSetSwitch(&FocusGotoSP, "Moving focuser to new calculated position based on temperature...");
674  return true;
675  }
676  else
677  {
678  IUResetSwitch(&FocusGotoSP);
679  FocusGotoSP.s = IPS_ALERT;
680  IDSetSwitch(&FocusGotoSP, "Failed to move focuser to home position!");
681  return true;
682  }
683  }
684 
685  IDSetSwitch(&FocusGotoSP, nullptr);
686  return true;
687  }
688  // handle quiet mode on/off
689  if (!strcmp(FocusTelemetrySP.name, name))
690  {
691  IUUpdateSwitch(&FocusTelemetrySP, states, names, n);
692 
693 
694  bool quiet = false;
695 
696  ISwitch *sp = IUFindOnSwitch(&FocusTelemetrySP);
697 
698  // Telemetry off
699  if (!strcmp(sp->name, "FOCUS_TELEMETRY_OFF"))
700  {
701  dispatch_command(FQUIET, 1);
702  quiet = true;
703  }
704  // Telemetry On
705  else
706  dispatch_command(FQUIET, 0);
707 
708  if (read_tcfs(response) == false)
709  {
710  IUResetSwitch(&FocusTelemetrySP);
711  FocusTelemetrySP.s = IPS_ALERT;
712  IDSetSwitch(&FocusTelemetrySP, "Error reading TCF-S reply.");
713  return true;
714  }
715 
716  if (isSimulation())
717  strncpy(response, "DONE", TCFS_MAX_CMD);
718 
719  if (strcmp(response, "DONE") == 0)
720  {
721  FocusTelemetrySP.s = IPS_OK;
722  IDSetSwitch(&FocusTelemetrySP,
723  quiet ? "Focuser Telemetry is off." : "Focuser Telemetry is on.");
724  // if (FocusTemperatureNP)
725  {
726  FocusTemperatureNP.s = quiet ? IPS_IDLE : IPS_OK;
727  IDSetNumber(&FocusTemperatureNP, nullptr);
728  }
729  return true;
730  }
731  else
732  {
733  FocusTelemetrySP.s = IPS_ALERT;
734  IDSetSwitch(&FocusTelemetrySP, "Focuser telemetry mode failed. Response: %s.", response);
735  return true;
736  }
737  }
738  }
739  return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
740 }
741 
742 IPState TCFS::MoveAbsFocuser(uint32_t targetTicks)
743 {
744  int delta = targetTicks - currentPosition;
745  LOGF_DEBUG("Moving to absolute position %d using offset %d", targetTicks, delta);
746  return MoveRelFocuser(delta < 0 ? FOCUS_INWARD : FOCUS_OUTWARD, std::abs(delta));
747 }
748 
750 {
751  // if (FocusModeSP.sp[0].s != ISS_ON)
752  // {
753  // LOG_WARN("The focuser can only be moved in Manual mode.");
754  // return IPS_ALERT;
755  // }
756  // The TCFS does not allow any commands othern than FMMODE whilst it is
757  // in auto mode. But this then prevents auto setting of filter offsets during
758  // an imaging sequence. So switch to manual mode, apply the offset then return
759  // to auto mode.
760  targetTicks = ticks;
761  targetPosition = currentPosition;
762 
763  TCFSMode prevMode = currentMode;
764  if(currentMode != MANUAL)
765  {
766  SetManualMode();
767  }
768  // Inward
769  if (dir == FOCUS_INWARD)
770  {
771  targetPosition -= targetTicks;
772  dispatch_command(FIN);
773 
774  LOGF_DEBUG("Moving inward by %d steps to position %d", targetTicks, targetPosition);
775  }
776  // Outward
777  else
778  {
779  targetPosition += targetTicks;
780  dispatch_command(FOUT);
781 
782  LOGF_DEBUG("Moving outward by %d steps to position %d", targetTicks, targetPosition);
783  }
784 
787  IDSetNumber(&FocusAbsPosNP, nullptr);
788  IDSetNumber(&FocusRelPosNP, nullptr);
789 
790  simulated_position = targetPosition;
791  if(prevMode != MANUAL)
792  {
793  IUResetSwitch(&FocusModeSP);
794  if (prevMode == MODE_A)
795  {
796  FocusModeSP.sp[1].s = ISS_ON;
797  }
798  else
799  {
800  FocusModeSP.sp[2].s = ISS_ON;
801  }
802  FocusModeSP.s = IPS_BUSY;
803  IDSetSwitch(&FocusModeSP, nullptr);
804  }
805 
806  return IPS_BUSY;
807 }
808 
809 bool TCFS::dispatch_command(TCFSCommand command_type, int val, TCFSMode m)
810 {
811  int err_code = 0, nbytes_written = 0;
812  char command[TCFS_MAX_CMD] = {0};
813 
814  switch (command_type)
815  {
816  // Focuser Manual Mode
817  case FMMODE:
818  strncpy(command, "FMMODE", TCFS_MAX_CMD);
819  break;
820 
821  // Focuser Free Mode
822  case FFMODE:
823  strncpy(command, "FFMODE", TCFS_MAX_CMD);
824  break;
825  // Focuser Auto-A Mode
826  case FAMODE:
827  strncpy(command, "FAMODE", TCFS_MAX_CMD);
828  break;
829 
830  // Focuser Auto-B Mode
831  case FBMODE:
832  strncpy(command, "FBMODE", TCFS_MAX_CMD);
833  break;
834 
835  // Focus Center
836  case FCENTR:
837  strncpy(command, "FCENTR", TCFS_MAX_CMD);
838  break;
839 
840  // Focuser In “nnnn”
841  case FIN:
842  simulated_position = currentPosition;
843 
844  snprintf(command, TCFS_MAX_CMD, "FI%04u", targetTicks);
845  break;
846 
847  // Focuser Out “nnnn”
848  case FOUT:
849  simulated_position = currentPosition;
850 
851  snprintf(command, TCFS_MAX_CMD, "FO%04u", targetTicks);
852  break;
853 
854  // Focuser Position Read Out
855  case FPOSRO:
856  strncpy(command, "FPOSRO", TCFS_MAX_CMD);
857  break;
858 
859  // Focuser Temperature
860  case FTMPRO:
861  strncpy(command, "FTMPRO", TCFS_MAX_CMD);
862  break;
863 
864  // Focuser Sleep
865  case FSLEEP:
866  strncpy(command, "FSLEEP", TCFS_MAX_CMD);
867  break;
868  // Focuser Wake Up
869  case FWAKUP:
870  strncpy(command, "FWAKUP", TCFS_MAX_CMD);
871  break;
872  // Focuser Home Command
873  case FHOME:
874  strncpy(command, "FHOME", TCFS_MAX_CMD);
875  break;
876  // Focuser Quiet Command
877  case FQUIET:
878  snprintf(command, TCFS_MAX_CMD, "FQUIT%01d", val);
879  break;
880  // Focuser Load Slope Command
881  case FLSLOP:
882  snprintf(command, TCFS_MAX_CMD, "FL%c%03d", m == MODE_A ? 'A' : 'B', abs(val));
883  break;
884  // Focuser Load Delay Command
885  case FDELAY:
886  snprintf(command, TCFS_MAX_CMD, "FD%c%03d", m == MODE_A ? 'A' : 'B', val);
887  break;
888  // Focuser Load Sign Command
889  case FLSIGN:
890  snprintf(command, TCFS_MAX_CMD, "FZ%cxx%01d", m == MODE_A ? 'A' : 'B', val >= 0 ? 0 : 1);
891  break;
892  // Focuser Read Slope Command
893  case FRSLOP:
894  snprintf(command, TCFS_MAX_CMD, "FREAD%c", m == MODE_A ? 'A' : 'B');
895  break;
896  // Focuser Read Sign Command
897  case FRSIGN:
898  snprintf(command, TCFS_MAX_CMD, "Ftxxx%c", m == MODE_A ? 'A' : 'B');
899  break;
900  case FFWVER:
901  snprintf(command, TCFS_MAX_CMD, "FVxxxx");
902  break;
903  }
904 
905  LOGF_DEBUG("CMD <%s>", command);
906 
907  if (isSimulation())
908  return true;
909 
910  tcflush(PortFD, TCIOFLUSH);
911 
912  if ( (err_code = tty_write(PortFD, command, strlen(command), &nbytes_written)) != TTY_OK)
913  {
914  char tcfs_error[TCFS_ERROR_BUFFER];
915  tty_error_msg(err_code, tcfs_error, TCFS_ERROR_BUFFER);
916  LOGF_ERROR("TTY error detected: %s", tcfs_error);
917  return false;
918  }
919 
920  return true;
921 }
922 
924 {
925  static double lastPosition = -1, lastTemperature = -1000;
926 
927  if (!isConnected())
928  {
930  return;
931  }
932 
933  char response[TCFS_MAX_CMD] = { 0 };
934  // If focuser is moving wait until "*" is received
935  // Then set moving indicator to OK
936  if (FocusRelPosNP.s == IPS_BUSY)
937  {
938  LOGF_DEBUG("%s Motion in Progress...", __FUNCTION__);
939  if (read_tcfs(response, true) == false)
940  {
942  return;
943  }
944  LOGF_DEBUG("%s READY %s", __FUNCTION__, response );
945  if(strcmp(response, "*") == 0)
946  {
949  IDSetNumber(&FocusAbsPosNP, nullptr);
950  IDSetNumber(&FocusRelPosNP, nullptr);
951 
952  // If the focuser has stopped moving and auto mode is requested then
953  // it is ok to set it now
954  if(FocusModeSP.s == IPS_BUSY && // Had to move before going Auto
955  (FocusModeSP.sp[1].s == ISS_ON || FocusModeSP.sp[2].s == ISS_ON))
956  {
957  const char* mode = (FocusModeSP.sp[1].s == ISS_ON) ? "A" : "B";
958  dispatch_command(
959  (FocusModeSP.sp[1].s == ISS_ON) ? FAMODE : FBMODE);
960  read_tcfs(response);
961  if (!isSimulation() && strcmp(response, mode) != 0)
962  {
963  IUResetSwitch(&FocusModeSP);
964  FocusModeSP.s = IPS_ALERT;
965  IDSetSwitch(&FocusModeSP, "Error switching to Auto Mode %s. No reply from TCF-S. Try again.", mode);
967  return;
968  }
969  FocusModeSP.s = IPS_OK;
970  LOGF_INFO("Entered Auto Mode %s", mode);
971  currentMode = (FocusModeSP.sp[1].s == ISS_ON) ? MODE_A : MODE_B;
972  IDSetSwitch(&FocusModeSP, nullptr);
973  }
975  return;
976  }
977  }
978 
979  int f_position = 0;
980  float f_temperature = 0;
981 
982  if(!isSimulation() && currentMode != MANUAL)
983  {
984  if (FocusTelemetrySP.sp[1].s == ISS_ON)
985  {
986  LOGF_DEBUG("%s %s", __FUNCTION__, "Telemetry is off");
988  return;
989  }
990  for(int i = 0; i < 2; i++)
991  {
992  if (read_tcfs(response, true) == false)
993  {
995  return;
996  }
997  LOGF_DEBUG("%s Received %s", __FUNCTION__, response);
998  if(sscanf(response, "P=%d", &f_position) == 1)
999  {
1000  currentPosition = f_position;
1001  if (lastPosition != currentPosition)
1002  {
1003  lastPosition = currentPosition;
1004  IDSetNumber(&FocusAbsPosNP, nullptr);
1005  }
1006  }
1007  else if(sscanf(response, "T=%f", &f_temperature) == 1)
1008  {
1009  FocusTemperatureNP.np[0].value = f_temperature;
1010 
1011  if (lastTemperature != FocusTemperatureNP.np[0].value)
1012  {
1013  lastTemperature = FocusTemperatureNP.np[0].value;
1014  IDSetNumber(&FocusTemperatureNP, nullptr);
1015  }
1016  }
1017  }
1019  return;
1020  }
1021 
1022  if (FocusGotoSP.s == IPS_BUSY)
1023  {
1024  ISwitch *sp = IUFindOnSwitch(&FocusGotoSP);
1025 
1026  if (sp != nullptr && strcmp(sp->name, "FOCUS_CENTER") == 0)
1027  {
1028  bool rc = read_tcfs(response, true);
1029 
1030  if (!rc)
1031  {
1033  return;
1034  }
1035 
1036  if (isSimulation())
1037  strncpy(response, "CENTER", TCFS_MAX_CMD);
1038 
1039  if (strcmp(response, "CENTER") == 0)
1040  {
1041  IUResetSwitch(&FocusGotoSP);
1042  FocusGotoSP.s = IPS_OK;
1044 
1045  IDSetSwitch(&FocusGotoSP, nullptr);
1046  IDSetNumber(&FocusAbsPosNP, nullptr);
1047 
1048  LOG_INFO("Focuser moved to center position.");
1049  }
1050  }
1051  }
1052 
1053  switch (FocusAbsPosNP.s)
1054  {
1055  case IPS_OK:
1056  if (FocusModeSP.sp[0].s == ISS_ON)
1057  dispatch_command(FPOSRO);
1058 
1059  if (read_tcfs(response) == false)
1060  {
1062  return;
1063  }
1064 
1065  if (isSimulation())
1066  snprintf(response, TCFS_MAX_CMD, "P=%04d", (int)simulated_position);
1067 
1068  sscanf(response, "P=%d", &f_position);
1069  currentPosition = f_position;
1070 
1071  if (lastPosition != currentPosition)
1072  {
1073  lastPosition = currentPosition;
1074  IDSetNumber(&FocusAbsPosNP, nullptr);
1075  }
1076  break;
1077 
1078  case IPS_BUSY:
1079  if (read_tcfs(response, true) == false)
1080  {
1082  return;
1083  }
1084 
1085  // Ignore error
1086  if (strstr(response, "ER") != nullptr)
1087  {
1088  LOGF_DEBUG("Received error: %s", response);
1090  return;
1091  }
1092 
1093  if (isSimulation())
1094  strncpy(response, "*", 2);
1095 
1096  if (strcmp(response, "*") == 0)
1097  {
1098  LOGF_DEBUG("Moving focuser %d steps to position %d.", targetTicks, targetPosition);
1101  FocusGotoSP.s = IPS_OK;
1102  IDSetNumber(&FocusAbsPosNP, nullptr);
1103  IDSetNumber(&FocusRelPosNP, nullptr);
1104  IDSetSwitch(&FocusGotoSP, nullptr);
1105  }
1106  else
1107  {
1109  LOGF_ERROR("Unable to read response from focuser #%s#.", response);
1110  IDSetNumber(&FocusAbsPosNP, nullptr);
1111  }
1112  break;
1113 
1114  default:
1115  break;
1116  }
1117 
1118  if (FocusTemperatureNP.s == IPS_OK || FocusTemperatureNP.s == IPS_BUSY)
1119  {
1120  // Read Temperature
1121  // Manual Mode
1122  if (FocusModeSP.sp[0].s == ISS_ON)
1123  dispatch_command(FTMPRO);
1124 
1125  if (read_tcfs(response) == false)
1126  {
1127  FocusTemperatureNP.s = IPS_ALERT;
1128  IDSetNumber(&FocusTemperatureNP, nullptr);
1129  LOG_ERROR("Failed to read temperature. Is sensor connected?");
1130 
1132  return;
1133  }
1134 
1135  if (isSimulation())
1136  snprintf(response, TCFS_MAX_CMD, "T=%0.1f", simulated_temperature);
1137 
1138  int rc = sscanf(response, "T=%f", &f_temperature);
1139 
1140  if (rc == 1)
1141  {
1142  FocusTemperatureNP.np[0].value = f_temperature;
1143 
1144  if (fabs(lastTemperature - FocusTemperatureNP.np[0].value) > 0.01)
1145  {
1146  lastTemperature = FocusTemperatureNP.np[0].value;
1147  IDSetNumber(&FocusTemperatureNP, nullptr);
1148  }
1149  }
1150  else
1151  {
1152  FocusTemperatureNP.s = IPS_ALERT;
1153  LOGF_ERROR("Failed to read temperature: %s", response);
1154  IDSetNumber(&FocusTemperatureNP, nullptr);
1155  }
1156  }
1157 
1159 }
1160 
1161 bool TCFS::read_tcfs(char *response, bool silent)
1162 {
1163  int err_code = 0, nbytes_read = 0;
1164 
1165  if (isSimulation())
1166  {
1167  strncpy(response, "SIMULATION", TCFS_MAX_CMD);
1168  return true;
1169  }
1170 
1171  // Read until encountring a CR
1172  if ((err_code = tty_read_section(PortFD, response, 0x0D, 2, &nbytes_read)) != TTY_OK)
1173  {
1174  if (!silent)
1175  {
1176  char err_msg[TCFS_ERROR_BUFFER];
1177  tty_error_msg(err_code, err_msg, 32);
1178  LOGF_ERROR("TTY error detected: %s", err_msg);
1179  }
1180 
1181  return false;
1182  }
1183 
1184  // Remove LF & CR
1185  response[nbytes_read - 2] = '\0';
1186 
1187  tcflush(PortFD, TCIOFLUSH);
1188 
1189  if (strstr(response, "ER="))
1190  {
1191  int errorCode = 0;
1192  sscanf(response, "ER=%d", &errorCode);
1193  LOGF_ERROR("Error Code <%d>", errorCode);
1194  return false;
1195  }
1196 
1197  LOGF_DEBUG("RES <%s>", response);
1198  return true;
1199 }
1200 
1202 {
1203  return mydev;
1204 }
INDI::FocuserInterface::FOCUSER_CAN_ABS_MOVE
@ FOCUSER_CAN_ABS_MOVE
Definition: indifocuserinterface.h:74
TCFS::FQUIET
@ FQUIET
Definition: tcfs.h:50
TCFS::FHOME
@ FHOME
Definition: tcfs.h:47
TCFS::FRSIGN
@ FRSIGN
Definition: tcfs.h:52
IP_RO
@ IP_RO
Definition: indiapi.h:183
TCFS::FPOSRO
@ FPOSRO
Definition: tcfs.h:43
TCFS::Handshake
virtual bool Handshake() override
perform handshake with device to check communication
Definition: tcfs.cpp:249
INDI::FocuserInterface::FOCUSER_CAN_REL_MOVE
@ FOCUSER_CAN_REL_MOVE
Definition: indifocuserinterface.h:75
INDI::FocuserInterface::FocusAbsPosNP
INumberVectorProperty FocusAbsPosNP
Definition: indifocuserinterface.h:282
INDI::DefaultDevice::addAuxControls
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
Definition: defaultdevice.cpp:665
tcfs.h
TCFS::FRSLOP
@ FRSLOP
Definition: tcfs.h:48
IPState
IPState
Property state.
Definition: indiapi.h:158
TCFS::MANUAL
@ MANUAL
Definition: tcfs.h:59
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
ISwitch
One switch descriptor.
ISS_OFF
@ ISS_OFF
Definition: indiapi.h:150
indicom.h
Implementations for common driver routines.
TCFS::FDELAY
@ FDELAY
Definition: tcfs.h:51
TCFS::FFWVER
@ FFWVER
Definition: tcfs.h:54
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
INDI::DefaultDevice::isSimulation
bool isSimulation() const
Definition: defaultdevice.cpp:734
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
TCFS::Disconnect
virtual bool Disconnect() override
Disconnect from device.
Definition: tcfs.cpp:306
TCFS::FMMODE
@ FMMODE
Definition: tcfs.h:36
TCFS::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: tcfs.cpp:320
TCFS::TimerHit
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition: tcfs.cpp:923
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
TCFS_MAX_CMD
#define TCFS_MAX_CMD
Definition: tcfs.h:28
TCFS::FLSLOP
@ FLSLOP
Definition: tcfs.h:49
TCFS::TCFSMode
TCFSMode
Definition: tcfs.h:57
INDI::Focuser::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
Definition: indifocuser.cpp:241
INDI::DefaultDevice::setVersion
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
Definition: defaultdevice.cpp:1219
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
INDI::Focuser::serialConnection
Connection::Serial * serialConnection
Definition: indifocuser.h:113
mydev
#define mydev
Definition: tcfs.cpp:32
tty_read_section
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition: indicom.c:557
Connection::Serial::B_19200
@ B_19200
Definition: connectionserial.h:82
IUSaveConfigNumber
void IUSaveConfigNumber(FILE *fp, const INumberVectorProperty *nvp)
Add a number vector property value to the configuration file.
Definition: indicom.c:1455
INDI::BaseDevice::getSwitch
INDI::PropertyView< ISwitch > * getSwitch(const char *name) const
Definition: basedevice.cpp:109
LOG_INFO
#define LOG_INFO(txt)
Definition: indilogger.h:74
max
double max(void)
TCFS::FFMODE
@ FFMODE
Definition: tcfs.h:37
IUResetSwitch
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indicom.c:1442
TCFS::GetFocusParams
void GetFocusParams()
Definition: tcfs.cpp:196
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
TCFS::MoveAbsFocuser
virtual IPState MoveAbsFocuser(uint32_t targetTicks) override
MoveFocuser the focuser to an absolute position.
Definition: tcfs.cpp:742
IUFindOnSwitch
ISwitch * IUFindOnSwitch(const ISwitchVectorProperty *sp)
Returns the first ON switch it finds in the vector switch property.
Definition: indicom.c:1414
TCFS::FAMODE
@ FAMODE
Definition: tcfs.h:38
INDI::DefaultDevice::getCurrentPollingPeriod
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
Definition: defaultdevice.cpp:1139
ISNewNumber
void ISNewNumber(const char *dev, const char *name, double *values, char *names[], int n)
Update the value of an existing number vector property.
LOGF_DEBUG
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
TCFS::FTMPRO
@ FTMPRO
Definition: tcfs.h:44
Connection::Serial::setDefaultBaudRate
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
Definition: connectionserial.cpp:381
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
tty_write
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition: indicom.c:415
TCFS::MoveRelFocuser
virtual IPState MoveRelFocuser(FocusDirection dir, uint32_t ticks) override
MoveFocuser the focuser to an relative position.
Definition: tcfs.cpp:749
TCFS_ERROR_BUFFER
#define TCFS_ERROR_BUFFER
Definition: tcfs.h:29
INDI::FocuserInterface::FOCUS_INWARD
@ FOCUS_INWARD
Definition: indifocuserinterface.h:68
TCFS::FCENTR
@ FCENTR
Definition: tcfs.h:40
TCFS::FIN
@ FIN
Definition: tcfs.h:41
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
connectionserial.h
_INumberVectorProperty::np
INumber * np
Definition: indiapi.h:334
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
INDI::FocuserInterface::FocusMotionSP
ISwitchVectorProperty FocusMotionSP
Definition: indifocuserinterface.h:274
INDI::FocuserInterface::FocusRelPosN
INumber FocusRelPosN[1]
Definition: indifocuserinterface.h:287
TCFS
Definition: tcfs.h:31
TCFS::FOUT
@ FOUT
Definition: tcfs.h:42
TCFS::FSLEEP
@ FSLEEP
Definition: tcfs.h:45
ISR_ATMOST1
@ ISR_ATMOST1
Definition: indiapi.h:173
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
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
TCFS::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: tcfs.cpp:54
LOG_DEBUG
#define LOG_DEBUG(txt)
Definition: indilogger.h:75
TCFS::FBMODE
@ FBMODE
Definition: tcfs.h:39
LOGF_INFO
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
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
name
const char * name
Definition: indiserver.c:116
TCFS::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Focuser Presets in the configuration file
Definition: tcfs.cpp:176
TCFS::FLSIGN
@ FLSIGN
Definition: tcfs.h:53
_ISwitchVectorProperty::s
IPState s
Definition: indiapi.h:382
INDI::FocuserInterface::FocusMaxPosN
INumber FocusMaxPosN[1]
Definition: indifocuserinterface.h:291
TCFS::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
Definition: tcfs.cpp:403
IUUpdateNumber
int IUUpdateNumber(INumberVectorProperty *nvp, double values[], char *names[], int n)
Update all numbers in a number vector property.
Definition: indidriver.c:225
TCFS::FWAKUP
@ FWAKUP
Definition: tcfs.h:46
TCFS::getDefaultName
const char * getDefaultName() override
Definition: tcfs.cpp:1201
INDI::FocuserInterface::FocusDirection
FocusDirection
Definition: indifocuserinterface.h:66
IP_RW
@ IP_RW
Definition: indiapi.h:185
LOG_WARN
#define LOG_WARN(txt)
Definition: indilogger.h:73
TCFS::MODE_A
@ MODE_A
Definition: tcfs.h:60
ISState
ISState
Switch state.
Definition: indiapi.h:148
_ISwitchVectorProperty::sp
ISwitch * sp
Definition: indiapi.h:384
TCFS::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: tcfs.cpp:140
me
char * me
Definition: indidriver.c:50
TCFS::SetManualMode
bool SetManualMode()
Definition: tcfs.cpp:284
IUSaveConfigSwitch
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition: indicom.c:1465
INDI::Focuser::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indifocuser.cpp:58
INDI::DefaultDevice::Disconnect
virtual bool Disconnect()
Disconnect from device.
Definition: defaultdevice.cpp:1083
TTY_OK
@ TTY_OK
Definition: indicom.h:94
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.
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
currentPosition
#define currentPosition
Definition: tcfs.cpp:33
_ISwitchVectorProperty
Switch vector property descriptor.
Definition: indiapi.h:365
TCFS::TCFS
TCFS()
Definition: tcfs.cpp:42
_ISwitchVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:370
ISS_ON
@ ISS_ON
Definition: indiapi.h:151
TCFS::MODE_B
@ MODE_B
Definition: tcfs.h:61
INDI::FocuserInterface::FOCUS_OUTWARD
@ FOCUS_OUTWARD
Definition: indifocuserinterface.h:69