Instrument Neutral Distributed Interface INDI  2.0.2
scopedome_usb21.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  ScopeDome Dome INDI Driver
3 
4  Copyright(c) 2017-2021 Jarno Paananen. All rights reserved.
5 
6  based on:
7 
8  ScopeDome Windows ASCOM driver version 5.1.30
9 
10  This library is free software; you can redistribute it and/or
11  modify it under the terms of the GNU Library General Public
12  License version 2 as published by the Free Software Foundation.
13  .
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Library General Public License for more details.
18  .
19  You should have received a copy of the GNU Library General Public License
20  along with this library; see the file COPYING.LIB. If not, write to
21  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  Boston, MA 02110-1301, USA.
23 *******************************************************************************/
24 
25 #include "scopedome_usb21.h"
26 #include "indicom.h"
27 
28 #include <termios.h>
29 #include <unistd.h>
30 
31 #define SCOPEDOME_TIMEOUT 2
32 
33 static const uint8_t header = 0xaa;
34 
36 {
37  int rc = -1;
38  Command cmd;
39  LOGF_DEBUG("Detect! %d", rc);
40  rc = write(ConnectionTest);
41  LOGF_DEBUG("write rc: %d", rc);
42  rc = read(cmd);
43  LOGF_DEBUG("read rc: %d, cmd %d", rc, (int)cmd);
44 
45  if (cmd != ConnectionTest)
46  {
47  return false;
48  }
49  // Disable "safe" communication mode that resets connection after few seconds
50  rc = write(StopSafeCommunication);
51  rc = read(cmd);
52  return (cmd == StopSafeCommunication);
53 }
54 
55 uint8_t ScopeDomeUSB21::CRC(uint8_t crc, uint8_t data)
56 {
57  crc ^= data;
58 
59  for (int i = 0; i < 8; i++)
60  {
61  if (crc & 1)
62  crc = ((crc >> 1) ^ 0x8C);
63  else
64  crc >>= 1;
65  }
66  return crc;
67 }
68 
69 int ScopeDomeUSB21::writeBuf(Command cmd, uint8_t len, uint8_t *buff)
70 {
71  int BytesToWrite = len + 4;
72  int nbytes_written = 0, rc = -1;
73  char errstr[MAXRBUF];
74 
75  uint8_t cbuf[BytesToWrite];
76  cbuf[0] = header;
77  cbuf[3] = CRC(0, cbuf[0]);
78  cbuf[1] = len;
79  cbuf[3] = CRC(cbuf[3], cbuf[1]);
80  cbuf[2] = cmd;
81  cbuf[3] = CRC(cbuf[3], cbuf[2]);
82 
83  for (int i = 0; i < len; i++)
84  {
85  cbuf[i + 4] = buff[i];
86  cbuf[3] = CRC(cbuf[3], buff[i]);
87  }
88 
89  tcflush(PortFD, TCIOFLUSH);
90 
91  prevcmd = cmd;
92 
93  // Write buffer
94  if ((rc = tty_write(PortFD, (const char *)cbuf, sizeof(cbuf), &nbytes_written)) != TTY_OK)
95  {
96  tty_error_msg(rc, errstr, MAXRBUF);
97  LOGF_ERROR("Error writing command: %s. Cmd %d", errstr, cmd);
98  }
99  return rc;
100 }
101 
102 int ScopeDomeUSB21::write(Command cmd)
103 {
104  int nbytes_written = 0, rc = -1;
105  uint8_t cbuf[4];
106  char errstr[MAXRBUF];
107 
108  tcflush(PortFD, TCIOFLUSH);
109 
110  cbuf[0] = header;
111  cbuf[3] = CRC(0, cbuf[0]);
112  cbuf[1] = 0;
113  cbuf[3] = CRC(cbuf[3], cbuf[1]);
114  cbuf[2] = cmd;
115  cbuf[3] = CRC(cbuf[3], cbuf[2]);
116 
117  prevcmd = cmd;
118 
119  // Write buffer
120  LOGF_DEBUG("write cmd: %x %x %x %x", cbuf[0], cbuf[1], cbuf[2], cbuf[3]);
121  if ((rc = tty_write(PortFD, (const char *)cbuf, sizeof(cbuf), &nbytes_written)) != TTY_OK)
122  {
123  tty_error_msg(rc, errstr, MAXRBUF);
124  LOGF_ERROR("Error writing command: %s. Cmd: %d", errstr, cmd);
125  }
126  return rc;
127 }
128 
129 int ScopeDomeUSB21::readBuf(Command &cmd, uint8_t len, uint8_t *buff)
130 {
131  int nbytes_read = 0, rc = -1;
132  int BytesToRead = len + 4;
133  uint8_t cbuf[BytesToRead];
134  char errstr[MAXRBUF];
135 
136  // Read buffer
137  if ((rc = tty_read(PortFD, (char *)cbuf, sizeof(cbuf), SCOPEDOME_TIMEOUT, &nbytes_read)) != TTY_OK)
138  {
139  tty_error_msg(rc, errstr, MAXRBUF);
140  LOGF_ERROR("Error reading: %s. Cmd: %d", errstr, prevcmd);
141  return rc;
142  }
143 
144  LOGF_DEBUG("readbuf cmd: %x %x %x %x", cbuf[0], cbuf[1], cbuf[2], cbuf[3]);
145  uint8_t Checksum = CRC(0, cbuf[0]);
146  Checksum = CRC(Checksum, cbuf[1]);
147  cmd = (Command)cbuf[2];
148  Checksum = CRC(Checksum, cbuf[2]);
149 
150  for (int i = 0; i < len; i++)
151  {
152  buff[i] = cbuf[i + 4];
153  Checksum = CRC(Checksum, cbuf[i + 4]);
154  }
155 
156  if (cbuf[3] != Checksum)
157  {
158  LOGF_ERROR("readbuf checksum error, cmd: %d", prevcmd);
159  return CHECKSUM_ERROR;
160  }
161  if (cmd == FunctionNotSupported)
162  {
163  LOG_ERROR("readbuf not supported error");
164  return FUNCTION_NOT_SUPPORTED_BY_FIRMWARE;
165  }
166 
167  if (cbuf[1] != len)
168  {
169  LOGF_ERROR("readbuf packet length error, cmd: %d", prevcmd);
170  return PACKET_LENGTH_ERROR;
171  }
172  return rc;
173 }
174 
175 int ScopeDomeUSB21::read(Command &cmd)
176 {
177  int nbytes_read = 0, rc = -1;
178  int err = 0;
179  uint8_t cbuf[4] = { 0 };
180  char errstr[MAXRBUF];
181 
182  // Read buffer
183  if ((rc = tty_read(PortFD, (char *)cbuf, sizeof(cbuf), SCOPEDOME_TIMEOUT, &nbytes_read)) != TTY_OK)
184  {
185  tty_error_msg(rc, errstr, MAXRBUF);
186  LOGF_ERROR("Error reading: %s. Cmd %d", errstr, prevcmd);
187  return rc;
188  }
189 
190  LOGF_DEBUG("read cmd: %x %x %x %x", cbuf[0], cbuf[1], cbuf[2], cbuf[3]);
191  uint8_t Checksum = CRC(0, cbuf[0]);
192  Checksum = CRC(Checksum, cbuf[1]);
193  cmd = (Command)cbuf[2];
194  Checksum = CRC(Checksum, cbuf[2]);
195 
196  if (cbuf[3] != Checksum || cbuf[1] != 0)
197  {
198  LOGF_ERROR("read checksum error, cmd: %d", prevcmd);
199  return CHECKSUM_ERROR;
200  }
201  switch (cmd)
202  {
203  case MotionConflict:
204  LOG_ERROR("read motion conflict");
205  err = MOTION_CONFLICT;
206  break;
207 
208  case FunctionNotSupported:
209  LOG_ERROR("read function not supported");
210  err = FUNCTION_NOT_SUPPORTED;
211  break;
212 
213  case ParamError:
214  LOG_ERROR("read param error");
215  err = PARAM_ERROR;
216  break;
217  default:
218  break;
219  }
220  return err;
221 }
222 
223 /************************************************************************************
224  *
225  * ***********************************************************************************/
226 bool ScopeDomeUSB21::readFloat(Command cmd, float &dst)
227 {
228  float value;
229  Command c;
230  int rc;
231  int retryCount = 2;
232  do
233  {
234  rc = write(cmd);
235  if (rc == 0)
236  rc = readBuf(c, 4, (uint8_t *)&value);
237  else
238  reconnect();
239  }
240  while (rc != 0 && --retryCount);
241  LOGF_DEBUG("readFloat: %d %f", cmd, value);
242  if (rc == 0)
243  {
244  dst = value;
245  return true;
246  }
247  return false;
248 }
249 
250 bool ScopeDomeUSB21::readU8(Command cmd, uint8_t &dst)
251 {
252  uint8_t value;
253  Command c;
254  int rc;
255  int retryCount = 2;
256  do
257  {
258  rc = write(cmd);
259  if (rc == 0)
260  rc = readBuf(c, 1, &value);
261  else
262  reconnect();
263  }
264  while (rc != 0 && --retryCount);
265  LOGF_DEBUG("readU8: %d %x", cmd, value);
266  if (rc == 0)
267  {
268  dst = value;
269  return true;
270  }
271  return false;
272 }
273 
274 bool ScopeDomeUSB21::readS8(Command cmd, int8_t &dst)
275 {
276  int8_t value;
277  Command c;
278  int rc;
279  int retryCount = 2;
280  do
281  {
282  rc = write(cmd);
283  if (rc == 0)
284  rc = readBuf(c, 1, (uint8_t *)&value);
285  else
286  reconnect();
287  }
288  while (rc != 0 && --retryCount);
289  LOGF_DEBUG("readS8: %d %x", cmd, value);
290  if (rc == 0)
291  {
292  dst = value;
293  return true;
294  }
295  return false;
296 }
297 
298 bool ScopeDomeUSB21::readU16(Command cmd, uint16_t &dst)
299 {
300  uint16_t value;
301  Command c;
302  int rc;
303  int retryCount = 2;
304  do
305  {
306  rc = write(cmd);
307  if (rc == 0)
308  rc = readBuf(c, 2, (uint8_t *)&value);
309  else
310  reconnect();
311  }
312  while (rc != 0 && --retryCount);
313  LOGF_DEBUG("readU16: %d %x", cmd, value);
314  if (rc == 0)
315  {
316  dst = value;
317  return true;
318  }
319  return false;
320 }
321 
322 bool ScopeDomeUSB21::readS16(Command cmd, int16_t &dst)
323 {
324  int16_t value;
325  Command c;
326  int rc;
327  int retryCount = 2;
328  do
329  {
330  rc = write(cmd);
331  if (rc == 0)
332  rc = readBuf(c, 2, (uint8_t *)&value);
333  else
334  reconnect();
335  }
336  while (rc != 0 && --retryCount);
337  LOGF_DEBUG("readS16: %d %x", cmd, value);
338  if (rc == 0)
339  {
340  dst = value;
341  return true;
342  }
343  return false;
344 }
345 
346 bool ScopeDomeUSB21::readU32(Command cmd, uint32_t &dst)
347 {
348  uint32_t value;
349  Command c;
350  int rc;
351  int retryCount = 2;
352  do
353  {
354  rc = write(cmd);
355  if (rc == 0)
356  rc = readBuf(c, 4, (uint8_t *)&value);
357  else
358  reconnect();
359  }
360  while (rc != 0 && --retryCount);
361  LOGF_DEBUG("readU32: %d %x", cmd, value);
362  if (rc == 0)
363  {
364  dst = value;
365  return true;
366  }
367  return false;
368 }
369 
370 bool ScopeDomeUSB21::readS32(Command cmd, int32_t &dst)
371 {
372  int32_t value;
373  Command c;
374  int rc;
375  int retryCount = 2;
376  do
377  {
378  rc = write(cmd);
379  if (rc == 0)
380  rc = readBuf(c, 4, (uint8_t *)&value);
381  else
382  reconnect();
383  }
384  while (rc != 0 && --retryCount);
385  LOGF_DEBUG("readU32: %d %x", cmd, value);
386  if (rc == 0)
387  {
388  dst = value;
389  return true;
390  }
391  return false;
392 }
393 
394 int ScopeDomeUSB21::readBuffer(Command cmd, int len, uint8_t *cbuf)
395 {
396  int rc;
397  int retryCount = 2;
398  Command c;
399  do
400  {
401  rc = write(cmd);
402  if (rc == 0)
403  rc = readBuf(c, len, cbuf);
404  else
405  reconnect();
406  }
407  while (rc != 0 && --retryCount);
408  return rc;
409 }
410 
411 int ScopeDomeUSB21::writeCmd(Command cmd)
412 {
413  int rc = write(cmd);
414  if (rc != 0)
415  {
416  reconnect();
417  return rc;
418  }
419  return read(cmd);
420 }
421 
422 int ScopeDomeUSB21::writeU8(Command cmd, uint8_t value)
423 {
424  int rc = writeBuf(cmd, 1, &value);
425  if (rc != 0)
426  {
427  reconnect();
428  return rc;
429  }
430  return read(cmd);
431 }
432 
433 int ScopeDomeUSB21::writeU16(Command cmd, uint16_t value)
434 {
435  int rc = writeBuf(cmd, 2, (uint8_t *)&value);
436  if (rc != 0)
437  {
438  reconnect();
439  return rc;
440  }
441  return read(cmd);
442 }
443 
444 int ScopeDomeUSB21::writeU32(Command cmd, uint32_t value)
445 {
446  int rc = writeBuf(cmd, 4, (uint8_t *)&value);
447  if (rc != 0)
448  {
449  reconnect();
450  return rc;
451  }
452  return read(cmd);
453 }
454 
455 int ScopeDomeUSB21::writeBuffer(Command cmd, int len, uint8_t *cbuf)
456 {
457  int rc = writeBuf(cmd, len, cbuf);
458  if (rc != 0)
459  {
460  reconnect();
461  return rc;
462  }
463  return read(cmd);
464 }
465 
466 void ScopeDomeUSB21::reconnect()
467 {
468  parent->reconnect();
469 }
470 
472 {
473  int rc = readU16(GetStatus, status);
474  rc |= readS16(GetCounter, counter);
475  rc |= readBuffer(GetAllDigitalExt, 5, digitalSensorState);
476  return rc;
477 }
478 
480 {
481  return status;
482 }
483 
484 void ScopeDomeUSB21::getFirmwareVersions(double &main, double &rotary)
485 {
486  uint16_t fwVersion = 0;
487  readU16(GetVersionFirmware, fwVersion);
488  main = fwVersion / 100.0;
489 
490  uint8_t fwVersionRotary = 0;
491  readU8(GetVersionFirmwareRotary, fwVersionRotary);
492  rotary = (fwVersionRotary + 9) / 10.0;
493 }
494 
496 {
497  uint32_t stepsPerRevolution = 0;
498  readU32(GetImpPerTurn, stepsPerRevolution);
499  return stepsPerRevolution;
500 }
501 
502 // Abstract versions
504 {
505  DigitalIO channel;
506  switch(input)
507  {
508  case HOME:
509  channel = IN_HOME;
510  break;
511  case OPEN1:
512  channel = IN_OPEN1;
513  break;
514  case CLOSED1:
515  channel = IN_CLOSED1;
516  break;
517  case OPEN2:
518  channel = IN_OPEN2;
519  break;
520  case CLOSED2:
521  channel = IN_CLOSED1;
522  break;
523  case ROTARY_LINK:
524  channel = IN_ROT_LINK;
525  break;
526  default:
527  LOG_ERROR("invalid input");
528  return ISS_OFF;
529  }
530  return getInputState(channel);
531 }
532 
534 {
535  DigitalIO channel;
536  switch(output)
537  {
538  case RESET:
539  channel = OUT_RELAY1;
540  break;
541  case CW:
542  channel = OUT_CW;
543  break;
544  case CCW:
545  channel = OUT_CCW;
546  break;
547  default:
548  LOG_ERROR("invalid output");
549  return ISS_OFF;
550  }
551  return setOutputState(channel, onOff);
552 }
553 
554 // Internal versions
555 ISState ScopeDomeUSB21::getInputState(DigitalIO channel)
556 {
557  int ch = (int)channel;
558  int byte = ch >> 3;
559  uint8_t bit = 1 << (ch & 7);
560  return (digitalSensorState[byte] & bit) ? ISS_ON : ISS_OFF;
561 }
562 
563 int ScopeDomeUSB21::setOutputState(DigitalIO channel, ISState onOff)
564 {
565  return writeU8(onOff == ISS_ON ? SetDigitalChannel : ClearDigitalChannel, (uint8_t)channel);
566 }
567 
569 {
570  return counter;
571 }
572 
574 {
575  readS32(GetCounterExt, counterExt);
576  return counterExt;
577 }
578 
580 {
581  uint8_t calibrationNeeded = false;
582  readU8(IsFullSystemCalReq, calibrationNeeded);
583  return calibrationNeeded != 0;
584 }
585 
587 {
588  writeCmd(Stop);
589 }
590 
592 {
593  writeCmd(FullSystemCal);
594 }
595 
597 {
598  writeCmd(FindHome);
599 }
600 
602 {
603  switch(operation)
604  {
605  case OPEN_SHUTTER:
606  setOutputState(OUT_CLOSE1, ISS_OFF);
607  setOutputState(OUT_OPEN1, ISS_ON);
608  break;
609  case CLOSE_SHUTTER:
610  setOutputState(OUT_CLOSE1, ISS_ON);
611  setOutputState(OUT_OPEN1, ISS_OFF);
612  break;
613  case STOP_SHUTTER:
614  setOutputState(OUT_CLOSE1, ISS_OFF);
615  setOutputState(OUT_OPEN1, ISS_OFF);
616  break;
617  }
618 }
619 
621 {
622  writeCmd(ResetCounter);
623  writeCmd(ResetCounterExt);
624 }
625 
626 void ScopeDomeUSB21::move(int steps)
627 {
628  if(steps < 0)
629  {
630  writeU16(CCWRotation, -steps);
631  }
632  else
633  {
634  writeU16(CWRotation, steps);
635  }
636 }
637 
639 {
640  return 11;
641 }
642 
644 {
646  switch(index)
647  {
648  case 0:
649  info.propName = "LINK_STRENGTH";
650  info.label = "Shutter link strength";
651  info.format = "%3.0f";
652  info.minValue = 0;
653  info.maxValue = 100;
654  break;
655  case 1:
656  info.propName = "SHUTTER_POWER";
657  info.label = "Shutter internal power";
658  info.format = "%2.2f";
659  info.minValue = 0;
660  info.maxValue = 100;
661  break;
662  case 2:
663  info.propName = "SHUTTER_BATTERY";
664  info.label = "Shutter battery power";
665  info.format = "%2.2f";
666  info.minValue = 0;
667  info.maxValue = 100;
668  break;
669  case 3:
670  info.propName = "CARD_POWER";
671  info.label = "Card internal power";
672  info.format = "%2.2f";
673  info.minValue = 0;
674  info.maxValue = 100;
675  break;
676  case 4:
677  info.propName = "CARD_BATTERY";
678  info.label = "Card battery power";
679  info.format = "%2.2f";
680  info.minValue = 0;
681  info.maxValue = 100;
682  break;
683  case 5:
684  info.propName = "TEMP_DOME_IN";
685  info.label = "Temperature in dome";
686  info.format = "%2.2f";
687  info.minValue = -100;
688  info.maxValue = 100;
689  break;
690  case 6:
691  info.propName = "TEMP_DOME_OUT";
692  info.label = "Temperature outside dome";
693  info.format = "%2.2f";
694  info.minValue = -100;
695  info.maxValue = 100;
696  break;
697  case 7:
698  info.propName = "TEMP_DOME_HUMIDITY";
699  info.label = "Temperature humidity sensor";
700  info.format = "%2.2f";
701  info.minValue = -100;
702  info.maxValue = 100;
703  break;
704  case 8:
705  info.propName = "HUMIDITY";
706  info.label = "Humidity";
707  info.format = "%3.2f";
708  info.minValue = 0;
709  info.maxValue = 100;
710  break;
711  case 9:
712  info.propName = "PRESSURE";
713  info.label = "Pressure";
714  info.format = "%4.1f";
715  info.minValue = 0;
716  info.maxValue = 2000;
717  break;
718  case 10:
719  info.propName = "DEW_POINT";
720  info.label = "Dew point";
721  info.format = "%2.2f";
722  info.minValue = -100;
723  info.maxValue = 100;
724  break;
725  default:
726  LOG_ERROR("invalid sensor index");
727  break;
728  }
729  return info;
730 }
731 
732 double ScopeDomeUSB21::getSensorValue(size_t index)
733 {
734  double value = 0;
735 
736  switch(index)
737  {
738  case 0:
739  {
740  readU8(GetLinkStrength, linkStrength);
741  value = linkStrength;
742 
743  // My shutter unit occasionally disconnects so implement a simple watchdog
744  // to check for link strength and reset the controller if link is lost for
745  // more than 5 polling cycles
746  static int count = 0;
747  if (linkStrength == 0)
748  {
749  if (++count > 5)
750  {
751  // Issue reset
753  count = 0;
754  }
755  }
756  else
757  {
758  count = 0;
759  }
760  break;
761  }
762  case 1:
763  readFloat(GetAnalog1, sensors[0]);
764  value = sensors[0];
765  break;
766  case 2:
767  readFloat(GetAnalog2, sensors[1]);
768  value = sensors[1];
769  break;
770  case 3:
771  readFloat(GetMainAnalog1, sensors[2]);
772  value = sensors[2];
773  break;
774  case 4:
775  readFloat(GetMainAnalog2, sensors[3]);
776  value = sensors[3];
777  break;
778  case 5:
779  readFloat(GetTempIn, sensors[4]);
780  value = sensors[4];
781  break;
782  case 6:
783  readFloat(GetTempOut, sensors[5]);
784  value = sensors[5];
785  break;
786  case 7:
787  readFloat(GetTempHum, sensors[6]);
788  value = sensors[6];
789  break;
790  case 8:
791  readFloat(GetHum, sensors[7]);
792  value = sensors[7];
793  break;
794  case 9:
795  readFloat(GetPressure, sensors[8]);
796  value = sensors[8];
797  break;
798  case 10:
799  value = parent->getDewPoint(sensors[7], sensors[6]);
800  break;
801  default:
802  LOG_ERROR("invalid sensor index");
803  break;
804  }
805  return value;
806 }
807 
809 {
810  return 8;
811 }
812 
814 {
816  switch(index)
817  {
818  case 0:
819  info.propName = "CCD";
820  info.label = "CCD";
821  break;
822  case 1:
823  info.propName = "SCOPE";
824  info.label = "Telescope";
825  break;
826  case 2:
827  info.propName = "LIGHT";
828  info.label = "Light";
829  break;
830  case 3:
831  info.propName = "FAN";
832  info.label = "Fan";
833  break;
834  case 4:
835  info.propName = "RELAY_1";
836  info.label = "Relay 1 (reset)";
837  break;
838  case 5:
839  info.propName = "RELAY_2";
840  info.label = "Relay 2 (heater)";
841  break;
842  case 6:
843  info.propName = "RELAY_3";
844  info.label = "Relay 3";
845  break;
846  case 7:
847  info.propName = "RELAY_4";
848  info.label = "Relay 4";
849  break;
850  default:
851  LOG_ERROR("invalid relay index");
852  break;
853  }
854  return info;
855 }
856 
858 {
859  switch(index)
860  {
861  case 0:
862  return getInputState(OUT_CCD);
863  case 1:
864  return getInputState(OUT_SCOPE);
865  case 2:
866  return getInputState(OUT_LIGHT);
867  case 3:
868  return getInputState(OUT_FAN);
869  case 4:
870  return getInputState(OUT_RELAY1);
871  case 5:
872  return getInputState(OUT_RELAY2);
873  case 6:
874  return getInputState(OUT_RELAY3);
875  case 7:
876  return getInputState(OUT_RELAY4);
877  default:
878  LOG_ERROR("invalid relay index");
879  break;
880  }
881  return ISS_OFF;
882 }
883 
884 void ScopeDomeUSB21::setRelayState(size_t index, ISState state)
885 {
886  switch(index)
887  {
888  case 0:
889  setOutputState(OUT_CCD, state);
890  break;
891  case 1:
892  setOutputState(OUT_SCOPE, state);
893  break;
894  case 2:
895  setOutputState(OUT_LIGHT, state);
896  break;
897  case 3:
898  setOutputState(OUT_FAN, state);
899  break;
900  case 4:
901  setOutputState(OUT_RELAY1, state);
902  break;
903  case 5:
904  setOutputState(OUT_RELAY2, state);
905  break;
906  case 6:
907  setOutputState(OUT_RELAY3, state);
908  break;
909  case 7:
910  setOutputState(OUT_RELAY4, state);
911  break;
912  default:
913  LOG_ERROR("invalid relay index");
914  break;
915  }
916 }
917 
919 {
920  return 12;
921 }
922 
924 {
926 
927  switch(index)
928  {
929  case 0:
930  info.propName = "AZ_COUNTER";
931  info.label = "Az counter";
932  break;
933  case 1:
934  info.propName = "HOME";
935  info.label = "Dome at home";
936  break;
937  case 2:
938  info.propName = "OPEN_1";
939  info.label = "Shutter 1 open";
940  break;
941  case 3:
942  info.propName = "CLOSE_1";
943  info.label = "Shutter 1 closed";
944  break;
945  case 4:
946  info.propName = "OPEN_2";
947  info.label = "Shutter 2 open";
948  break;
949  case 5:
950  info.propName = "CLOSE_2";
951  info.label = "Shutter 2 closed";
952  break;
953  case 6:
954  info.propName = "SCOPE_HOME";
955  info.label = "Scope at home";
956  break;
957  case 7:
958  info.propName = "RAIN";
959  info.label = "Rain sensor";
960  break;
961  case 8:
962  info.propName = "CLOUD";
963  info.label = "Cloud sensor";
964  break;
965  case 9:
966  info.propName = "SAFE";
967  info.label = "Observatory safe";
968  break;
969  case 10:
970  info.propName = "LINK";
971  info.label = "Rotary link";
972  break;
973  case 11:
974  info.propName = "FREE";
975  info.label = "Free input";
976  break;
977  default:
978  LOG_ERROR("invalid input index");
979  break;
980  }
981  return info;
982 }
983 
985 {
986  switch(index)
987  {
988  case 0:
989  return getInputState(IN_ENCODER);
990  case 1:
991  return getInputState(IN_HOME);
992  case 2:
993  return getInputState(IN_OPEN1);
994  case 3:
995  return getInputState(IN_CLOSED1);
996  case 4:
997  return getInputState(IN_OPEN2);
998  case 5:
999  return getInputState(IN_CLOSED2);
1000  case 6:
1001  return getInputState(IN_S_HOME);
1002  case 7:
1003  return getInputState(IN_CLOUDS);
1004  case 8:
1005  return getInputState(IN_CLOUD);
1006  case 9:
1007  return getInputState(IN_SAFE);
1008  case 10:
1009  return getInputState(IN_ROT_LINK);
1010  case 11:
1011  return getInputState(IN_FREE);
1012  default:
1013  LOG_ERROR("invalid input index");
1014  break;
1015  }
1016  return ISS_OFF;
1017 }
1018 
1020 {
1021  uint8_t negate = 0;
1022  switch(polarity)
1023  {
1024  case ACTIVE_HIGH:
1025  negate = 0;
1026  break;
1027  case ACTIVE_LOW:
1028  negate = 1;
1029  break;
1030  }
1031 
1032  writeU8(NegHomeSensorActiveState, negate);
1033 }
virtual void calibrate() override
virtual void abort() override
virtual void getFirmwareVersions(double &main, double &rotary) override
virtual double getSensorValue(size_t index) override
virtual ISState getInputValue(size_t index) override
virtual int updateState() override
virtual int getRotationCounterExt() override
virtual uint32_t getStepsPerRevolution() override
virtual size_t getNumberOfRelays() override
virtual size_t getNumberOfInputs() override
virtual ISState getRelayState(size_t index) override
virtual int setOutputState(AbstractOutput output, ISState state) override
virtual void resetCounter() override
virtual uint32_t getStatus() override
virtual ISState getInputState(AbstractInput input) override
virtual void findHome() override
virtual bool detect() override
virtual size_t getNumberOfSensors() override
virtual int getRotationCounter() override
virtual RelayInfo getRelayInfo(size_t index) override
virtual bool isCalibrationNeeded() override
virtual SensorInfo getSensorInfo(size_t index) override
virtual void setRelayState(size_t index, ISState state) override
virtual void controlShutter(ShutterOperation operation) override
virtual void setHomeSensorPolarity(HomeSensorPolarity polarity) override
virtual InputInfo getInputInfo(size_t index) override
virtual void move(int steps) override
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ ISS_ON
Definition: indiapi.h:152
int tty_write(int fd, const char *buf, int nbytes, int *nbytes_written)
Writes a buffer to fd.
Definition: indicom.c:424
int tty_read(int fd, char *buf, int nbytes, int timeout, int *nbytes_read)
read buffer from terminal
Definition: indicom.c:482
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1167
Implementations for common driver routines.
@ TTY_OK
Definition: indicom.h:150
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition: indilogger.h:72
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
#define MAXRBUF
Definition: indiserver.cpp:102
Command
The Command enum includes all the command types sent to the various devices (motor,...
@ value
the parser finished reading a JSON value
__u8 cmd[4]
Definition: pwc-ioctl.h:2
#define SCOPEDOME_TIMEOUT
int main(int, char *[])