Instrument Neutral Distributed Interface INDI  2.0.2
stv.c
Go to the documentation of this file.
1 #if 0
2  STV Driver
3  Copyright (C) 2006 Markus Wildi, markus.wildi@datacomm.ch
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 #endif
20 
21 /* Standard headers */
22 
23 #include <cstring>
24 #include <sys/stat.h>
25 #include <stdio.h>
26 #include <zlib.h>
27 #include <unistd.h>
28 
29 #ifndef _WIN32
30 #include <termios.h>
31 #endif
32 
33 /* INDI Core headers */
34 
35 #include "indidevapi.h"
36 
37 /* INDI Eventloop mechanism */
38 
39 #include "eventloop.h"
40 
41 /* INDI Common Routines/RS232 */
42 
43 #include "indicom.h"
44 
45 /* Config parameters */
46 #include <config.h>
47 
48 /* Fits */
49 
50 #include <fitsio.h>
51 
52 /* STV's definitions */
53 
54 #include "stvdriver.h"
55 
56 /* Definitions */
57 
58 #define mydev "STV Guider" /* Device name */
59 #define CONNECTION_GROUP "Connection" /* Group name */
60 #define SETTINGS_GROUP "Setings" /* Group name */
61 #define BUTTONS_GROUP "Buttons and Knobs" /* Button Pannel */
62 #define IMAGE_GROUP "Download" /* Button Pannel */
63 
64 #define currentBuffer BufferN[0].value
65 #define currentX WindowingN[0].value
66 #define currentY WindowingN[1].value
67 #define currentLines WindowingN[2].value
68 #define currentLength WindowingN[3].value
69 
70 #define currentCompression CompressionS[0].s
71 
72 static int compression = OFF;
73 static int acquiring = OFF;
74 static int guiding = OFF;
75 static int processing = OFF;
76 
77 /* Fits (fli_ccd project) */
79 {
84 };
85 #define TEMPFILE_LEN 16
86 
87 /* Image (fli_ccd project)*/
88 
89 typedef struct
90 {
91  int width;
92  int height;
93  int frameType;
94  int expose;
95  unsigned short *img;
96 } img_t;
97 
98 static img_t *STVImg;
99 
100 /* Function adapted from fli_ccd project */
101 
102 void addFITSKeywords(fitsfile *fptr, IMAGE_INFO *image_info);
103 int writeFITS(const char *filename, IMAGE_INFO *image_info, char errmsg[]);
104 void uploadFile(const char *filename);
105 
106 /* File descriptor and call back id */
107 int fd;
108 static int cb = -1;
109 char tracking_buf[1024];
110 
111 /* Function prototypes */
112 int ISTerminateTXDisplay(void);
113 int ISRestoreTXDisplay(void);
114 int ISMessageImageInfo(int buffer, IMAGE_INFO *image_info);
115 int ISRequestImageData(int compression, int buffer, int x_offset, int y_offset, int length, int lines);
116 
117 int STV_LRRotaryDecrease(void);
118 int STV_LRRotaryIncrease(void);
119 int STV_UDRotaryDecrease(void);
120 int STV_UDRotaryIncrease(void);
121 
122 int STV_AKey(void);
123 int STV_BKey(void);
124 int STV_Setup(void);
125 int STV_Interrupt(void);
126 int STV_Focus(void);
127 int STV_Image(void);
128 int STV_Monitor(void);
129 int STV_Calibrate(void);
130 int STV_Track(void);
131 int STV_Display(void);
132 int STV_FileOps(void);
133 int STV_RequestImageInfo(int imagebuffer, IMAGE_INFO *image_info);
134 int STV_BufferStatus(int buffer);
135 int STV_RequestImage(int compression, int buffer, int x_offset, int y_offset, int *length, int *lines, int image[][320],
136  IMAGE_INFO *image_info);
137 int STV_Download(void);
138 int STV_TXDisplay(void);
139 int STV_TerminateTXDisplay(void);
140 int STV_RequestAck(void);
141 unsigned int STV_GetBits(unsigned int x, int p, int n);
142 int STV_PrintBuffer(unsigned char *cmdbuf, int n);
143 void handleError(ISwitchVectorProperty *svp, int err, const char *msg);
144 static void ISInit();
145 void ISCallBack(void);
146 
147 int init_serial(char *device_name, int bit_rate, int word_size, int parity, int stop_bits);
148 int STV_ReceivePacket(unsigned char *buf, int mode);
149 int STV_Connect(char *device, int baud);
150 int STV_SetDateTime(char *times);
151 double STV_SetCCDTemperature(double set_value);
152 
153 static IText StatusT[] = {
154  { "STATUS", "This driver", "is experimental, contact markus.wildi@datacomm.ch", 0, 0, 0 },
155 };
156 
157 static ITextVectorProperty StatusTP = { mydev, "STAUS", "Status", CONNECTION_GROUP,
158  IP_RO, ISR_1OFMANY, IPS_IDLE, StatusT,
159  NARRAY(StatusT), "", 0 };
160 
161 /* RS 232 Connection */
162 
163 static ISwitch PowerS[] = {
164  { "CONNECT", "Connect", ISS_OFF, 0, 0 },
165  { "DISCONNECT", "Disconnect", ISS_OFF, 0, 0 },
166 };
167 
168 static ISwitchVectorProperty PowerSP = { mydev, "CONNECTION", "Connection", CONNECTION_GROUP, IP_RW, ISR_1OFMANY,
169  0, IPS_IDLE, PowerS, NARRAY(PowerS), "", 0 };
170 
171 /* Serial Port */
172 
173 static IText PortT[] = { { "PORT", "Port", NULL, 0, 0, 0 }, { "SPEED", "Speed", NULL, 0, 0, 0 } };
174 
175 static ITextVectorProperty PortTP = {
176  mydev, "DEVICE_PORT", "Port", CONNECTION_GROUP, IP_RW, ISR_1OFMANY, IPS_IDLE, PortT, NARRAY(PortT), "", 0
177 };
178 
179 static ISwitch TXDisplayS[] = {
180 
181  { "1", "On", ISS_ON, 0, 0 },
182  { "2", "Off", ISS_OFF, 0, 0 },
183 };
184 
185 static ISwitchVectorProperty TXDisplaySP = {
186  mydev, "Update Display", "Update Display", CONNECTION_GROUP, IP_RW, ISR_1OFMANY,
187  0, IPS_IDLE, TXDisplayS, NARRAY(TXDisplayS), "", 0
188 };
189 
190 static IText DisplayCT[] = {
191 
192  { "DISPLAYC1", "Line 1", NULL, 0, 0, 0 },
193  { "DISPLAYC2", "Line 2", NULL, 0, 0, 0 }
194 };
195 
196 static ITextVectorProperty DisplayCTP = {
197  mydev, "DISPLAYC", "Display", CONNECTION_GROUP, IP_RO, ISR_1OFMANY, IPS_IDLE, DisplayCT, NARRAY(DisplayCT), "", 0
198 };
199 
200 static IText DisplayBT[] = {
201 
202  { "DISPLAYB1", "Line 1", NULL, 0, 0, 0 },
203  { "DISPLAYB2", "Line 2", NULL, 0, 0, 0 }
204 };
205 
206 static ITextVectorProperty DisplayBTP = {
207  mydev, "DISPLAYB", "Display", BUTTONS_GROUP, IP_RO, ISR_1OFMANY, IPS_IDLE, DisplayBT, NARRAY(DisplayBT), "", 0
208 };
209 
210 static IText DisplayDT[] = {
211 
212  { "DISPLAYD1", "Line 1", NULL, 0, 0, 0 },
213  { "DISPLAYD2", "Line 2", NULL, 0, 0, 0 }
214 };
215 
216 static ITextVectorProperty DisplayDTP = { mydev, "DISPLAYD", "Display", IMAGE_GROUP, IP_RO, ISR_1OFMANY,
217  IPS_IDLE, DisplayDT, NARRAY(DisplayDT), "", 0 };
218 
219 /* Setings */
220 
221 static IText UTCT[] = { { "UTC", "UTC", NULL, 0, 0, 0 } };
222 ITextVectorProperty UTCTP = { mydev, "TIME_UTC", "UTC Time", SETTINGS_GROUP, IP_RW, 0, IPS_IDLE, UTCT,
223  NARRAY(UTCT), "", 0 };
224 
225 static INumber SetCCDTemperatureN[] = {
226  { "TEMPERATURE", "Cel. -55.1, +25.2", "%6.1f", -55.8, 25.2, 0., 16., 0, 0, 0 },
227 
228 };
229 
230 static INumberVectorProperty SetCCDTemperatureNP = { mydev,
231  "CCD_TEMPERATURE",
232  "CCD Temperature",
234  IP_RW,
235  ISR_1OFMANY,
236  IPS_IDLE,
237  SetCCDTemperatureN,
238  NARRAY(SetCCDTemperatureN),
239  "",
240  0 };
241 
242 /* Buttons */
243 static ISwitch ControlS[] = {
244 
245  { "1", "Parameter", ISS_OFF, 0, 0 },
246  { "2", "Increase", ISS_OFF, 0, 0 },
247  { "3", "Decrease", ISS_OFF, 0, 0 },
248 
249 };
250 
251 static ISwitchVectorProperty ControlSP = { mydev, "ParaButtons", "Control", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
252  0, IPS_IDLE, ControlS, NARRAY(ControlS), "", 0 };
253 
254 static ISwitch ValueS[] = {
255 
256  { "1", "Value", ISS_OFF, 0, 0 },
257  { "2", "Increase", ISS_OFF, 0, 0 },
258  { "3", "Decrease", ISS_OFF, 0, 0 },
259 };
260 
261 static ISwitchVectorProperty ValueSP = { mydev, "ValueButtons", "Control", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
262  0, IPS_IDLE, ValueS, NARRAY(ValueS), "", 0 };
263 
264 static ISwitch AuxiliaryS[] = {
265 
266  { "1", "Setup", ISS_OFF, 0, 0 },
267  { "2", "Interrupt", ISS_OFF, 0, 0 },
268 
269 };
270 
271 static ISwitchVectorProperty AuxiliarySP = { mydev, "Auxilliary", "", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
272  0, IPS_IDLE, AuxiliaryS, NARRAY(AuxiliaryS), "", 0 };
273 
274 static ISwitch AcquireS[] = {
275 
276  { "1", "Focus", ISS_OFF, 0, 0 },
277  { "2", "Image", ISS_OFF, 0, 0 },
278  { "3", "Monitor", ISS_OFF, 0, 0 },
279 };
280 
281 static ISwitchVectorProperty AcquireSP = { mydev, "Acquire", "", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
282  0, IPS_IDLE, AcquireS, NARRAY(AcquireS), "", 0 };
283 
284 static ISwitch GuideS[] = {
285 
286  { "1", "Calibrate", ISS_OFF, 0, 0 },
287  { "2", "Track", ISS_OFF, 0, 0 },
288 };
289 
290 static ISwitchVectorProperty GuideSP = { mydev, "Guide", "", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
291  0, IPS_IDLE, GuideS, NARRAY(GuideS), "", 0 };
292 
293 static ISwitch ProcessS[] = {
294 
295  { "1", "Display/Crosshairs", ISS_OFF, 0, 0 },
296  { "2", "File Ops", ISS_OFF, 0, 0 },
297 };
298 
299 static ISwitchVectorProperty ProcessSP = { mydev, "Process", "", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
300  0, IPS_IDLE, ProcessS, NARRAY(ProcessS), "", 0 };
301 
302 static ISwitch CompressionS[] = {
303 
304  { "1", "On", ISS_OFF, 0, 0 },
305  { "2", "Off", ISS_OFF, 0, 0 },
306 };
307 
308 static ISwitchVectorProperty CompressionSP = { mydev, "Compression", "", IMAGE_GROUP,
310  CompressionS, NARRAY(CompressionS), "", 0 };
311 
312 static ISwitch BufferStatusS[] = {
313 
314  { "1", "Status", ISS_OFF, 0, 0 },
315 };
316 
317 static ISwitchVectorProperty BufferStatusSP = { mydev, "Buffers", "", IMAGE_GROUP, IP_RW,
318  ISR_1OFMANY, 0, IPS_IDLE, BufferStatusS, NARRAY(BufferStatusS),
319  "", 0 };
320 
321 static INumber BufferN[] = {
322  { "A0", "Number 1 - 32", "%6.0f", 1., 32., 0., 32., 0, 0, 0 },
323 };
324 
325 static INumberVectorProperty BufferNP = { mydev, "BUFFER_Number", "Buffer", IMAGE_GROUP, IP_RW, ISR_1OFMANY,
326  IPS_IDLE, BufferN, NARRAY(BufferN), "", 0 };
327 
328 static INumber WindowingN[] = {
329 
330  { "X", "Offset x", "%6.0f", 0., 199., 0., 0., 0, 0, 0 },
331  { "Y", "Offset y", "%6.0f", 0., 319., 0., 0., 0, 0, 0 },
332  { "HEIGHT", "Lines", "%6.0f", 1., 200., 0., 200., 0, 0, 0 },
333  { "WIDTH", "Length", "%6.0f", 1., 320., 0., 320., 0, 0, 0 },
334 };
335 
336 static INumberVectorProperty WindowingNP = { mydev, "CCD_FRAME", "Windowing", IMAGE_GROUP, IP_RW, ISR_1OFMANY,
337  IPS_IDLE, WindowingN, NARRAY(WindowingN), "", 0 };
338 
339 static ISwitch ImageInfoS[] = {
340 
341  { "1", "One Image", ISS_OFF, 0, 0 },
342  { "2", "All Images", ISS_OFF, 0, 0 },
343 };
344 
345 static ISwitchVectorProperty ImageInfoSP = { mydev, "Information", "", IMAGE_GROUP, IP_RW, ISR_1OFMANY,
346  0, IPS_IDLE, ImageInfoS, NARRAY(ImageInfoS), "", 0 };
347 
348 static ISwitch DownloadS[] = {
349 
350  { "1", "One Image", ISS_OFF, 0, 0 },
351  { "2", "All Images", ISS_OFF, 0, 0 },
352 };
353 
354 static ISwitchVectorProperty DownloadSP = { mydev, "Download", "", IMAGE_GROUP, IP_RW, ISR_1OFMANY,
355  0, IPS_IDLE, DownloadS, NARRAY(DownloadS), "", 0 };
356 
357 /* BLOB for sending image */
358 
359 static IBLOB imageB = { "CCD1", "Image", "", 0, 0, 0, 0, 0, 0, 0 };
360 
361 static IBLOBVectorProperty imageBP = { mydev, "Image", "Image", IMAGE_GROUP, IP_RO, 0, IPS_IDLE, &imageB, 1, "", 0 };
362 
363 /* Initlization routine */
364 
365 static void ISInit()
366 {
367  static int isInit = 0;
368 
369  if (isInit)
370  return;
371 
372  IUSaveText(&PortT[0], "/dev/ttyUSB0");
373  IUSaveText(&PortT[1], "115200");
374 
375  if ((DisplayCT[0].text = malloc(1024)) == NULL)
376  {
377  fprintf(stderr, "3:Memory allocation error");
378  return;
379  }
380  if ((DisplayCT[1].text = malloc(1024)) == NULL)
381  {
382  fprintf(stderr, "4:Memory allocation error");
383  return;
384  }
385  if ((DisplayBT[0].text = malloc(1024)) == NULL)
386  {
387  fprintf(stderr, "5:Memory allocation error");
388  return;
389  }
390  if ((DisplayBT[1].text = malloc(1024)) == NULL)
391  {
392  fprintf(stderr, "5:Memory allocation error");
393  return;
394  }
395  if ((DisplayDT[0].text = malloc(1024)) == NULL)
396  {
397  fprintf(stderr, "7:Memory allocation error");
398  return;
399  }
400  if ((DisplayDT[1].text = malloc(1024)) == NULL)
401  {
402  fprintf(stderr, "8:Memory allocation error");
403  return;
404  }
405 
406  if ((STVImg = malloc(sizeof(img_t))) == NULL)
407  {
408  fprintf(stderr, "9:Memory allocation error");
409  return;
410  }
411 
412  isInit = 1;
413 }
414 
415 void ISResetButtons(char *message)
416 {
417  ControlSP.s = IPS_IDLE;
418  IUResetSwitch(&ControlSP);
419  IDSetSwitch(&ControlSP, NULL);
420 
421  ValueSP.s = IPS_IDLE;
422  IUResetSwitch(&ValueSP);
423  IDSetSwitch(&ValueSP, NULL);
424 
425  AuxiliarySP.s = IPS_IDLE;
426  IUResetSwitch(&AuxiliarySP);
427  IDSetSwitch(&AuxiliarySP, NULL);
428 
429  AcquireSP.s = IPS_IDLE;
430  IUResetSwitch(&AcquireSP);
431  IDSetSwitch(&AcquireSP, NULL);
432 
433  GuideSP.s = IPS_IDLE;
434  IUResetSwitch(&GuideSP);
435  IDSetSwitch(&GuideSP, NULL);
436 
437  ProcessSP.s = IPS_IDLE;
438  IUResetSwitch(&ProcessSP);
439  IDSetSwitch(&ProcessSP, NULL);
440 
441  ImageInfoSP.s = IPS_IDLE;
442  IUResetSwitch(&ImageInfoSP);
443  IDSetSwitch(&ImageInfoSP, NULL);
444 
445  BufferStatusSP.s = IPS_IDLE;
446  IUResetSwitch(&BufferStatusSP);
447  IDSetSwitch(&BufferStatusSP, NULL);
448 
449  /* SP.s= IPS_IDLE ; */
450  /* IUResetSwitch(&SP); */
451  /* IDSetSwitch(&SP, NULL); */
452 
453  DownloadSP.s = IPS_IDLE;
454  IUResetSwitch(&DownloadSP);
455 
456  IDSetSwitch(&DownloadSP, "%s", message);
457 
458  return;
459 }
460 
461 /* This function is called when ever the file handle fd provides data */
463 {
464  int res;
465  int k, l, m;
466 
467  unsigned char buf[1024];
468 
469  IERmCallback(cb);
470  cb = -1;
471 
472  /* fprintf( stderr, "ISCallBack\n") ; */
473  /* if(( counter++ % 4) ==0){ */
474  /* fprintf( stderr, ".") ; */
475  /* } */
476 
477  if (PowerS[0].s == ISS_ON)
478  {
479  res = STV_ReceivePacket(buf, guiding);
480 
481  /* res= STV_PrintBuffer(buf,res) ; */
482 
483  DisplayCTP.s = IPS_IDLE;
484  IDSetText(&DisplayCTP, NULL);
485  DisplayBTP.s = IPS_IDLE;
486  IDSetText(&DisplayBTP, NULL);
487  DisplayDTP.s = IPS_IDLE;
488  IDSetText(&DisplayDTP, NULL);
489 
490  switch ((int)buf[1])
491  { /* STV cmd byte */
492 
493  case DISPLAY_ECHO:
494 
495  if (res < 0)
496  {
497  DisplayCTP.s = IPS_ALERT;
498  IDSetText(&DisplayCTP, NULL);
499  DisplayBTP.s = IPS_ALERT;
500  IDSetText(&DisplayBTP, NULL);
501  DisplayDTP.s = IPS_ALERT;
502  IDSetText(&DisplayDTP, NULL);
503  IDMessage(mydev, "Error while reading, continuing\n");
504  }
505  else
506  {
507  l = 0;
508  m = 0;
509  /* replace unprintable characters and format the string */
510  for (k = 0; k < 24; k++)
511  {
512  if (buf[k + 6] == 0x5e)
513  { /* first line */
514 
515  DisplayCT[0].text[l - 1] = 0x50; /* P */
516  DisplayCT[0].text[l++] = 0x6b; /* k */
517  }
518  else if (buf[k + 6] == 0xd7)
519  {
520  DisplayCT[0].text[l++] = 0x28; /* "(x,y) " */
521  DisplayCT[0].text[l++] = 0x78;
522  DisplayCT[0].text[l++] = 0x2c;
523  DisplayCT[0].text[l++] = 0x79;
524  DisplayCT[0].text[l++] = 0x29;
525  DisplayCT[0].text[l++] = 0x20;
526  }
527  else if (buf[k + 6] > 29 && buf[k + 6] < 127)
528  {
529  DisplayCT[0].text[l++] = buf[k + 6];
530  }
531  else
532  {
533  /* fprintf(stderr, "LINE 1%2x, %2x, %2x, %c %c %c\n", buf[k+ 5], buf[k+ 6], buf[k+ 7], buf[k+ 5], buf[k+ 6], buf[k+ 7]) ; */
534  DisplayCT[0].text[l++] = 0x20;
535  }
536  if (buf[k + 30] == 0xb0)
537  { /* second line */
538 
539  DisplayCT[1].text[m++] = 0x43; /* Celsius */
540  }
541  else if (buf[k + 30] > 29 && buf[k + 30] < 127)
542  {
543  DisplayCT[1].text[m++] = buf[k + 30];
544  }
545  else
546  {
547  /* fprintf(stderr, "LINE 2 %2x, %2x, %2x, %c %c %c\n", buf[k+ 29], buf[k+ 30], buf[k+ 31], buf[k+ 29], buf[k+ 30], buf[k+ 31]) ; */
548  DisplayCT[1].text[m++] = 0x20;
549  }
550  }
551  DisplayCT[0].text[l] = 0;
552  DisplayCT[1].text[m] = 0;
553 
554  strcpy(DisplayBT[0].text, DisplayCT[0].text);
555  strcpy(DisplayBT[1].text, DisplayCT[1].text);
556  strcpy(DisplayDT[0].text, DisplayCT[0].text);
557  strcpy(DisplayDT[1].text, DisplayCT[1].text);
558 
559  DisplayCTP.s = IPS_OK;
560  IDSetText(&DisplayCTP, NULL);
561  DisplayBTP.s = IPS_OK;
562  IDSetText(&DisplayBTP, NULL);
563  DisplayDTP.s = IPS_OK;
564  IDSetText(&DisplayDTP, NULL);
565  }
566  break;
567  case REQUEST_DOWNLOAD:
568 
569  /* fprintf(stderr, "STV says REQUEST_DOWNLOAD\n") ; */
570 
571  if (TXDisplayS[0].s == ISS_ON)
572  {
573  res = STV_Download();
574 
575  imageB.blob = NULL;
576  imageB.bloblen = 0;
577  imageB.size = 0;
578 
579  imageBP.s = IPS_ALERT;
580  IDSetBLOB(&imageBP, NULL);
581 
582  IDMessage(mydev, "Switch off display read out manually first (Update Display: Off\n)");
583  }
584  else
585  {
586  tcflush(fd, TCIOFLUSH);
587  usleep(100000);
588 
589  res = ISRequestImageData(1, 31, 0, 0, 320, 200); /* Download the on screen image (buffer 32 -1) */
590  }
591  /*fprintf(stderr, "STV END REQUEST_DOWNLOAD\n") ; */
592  break;
594 
595  IDMessage(mydev, "REQUEST_DOWNLOAD_ALL initiated at the STV not implemented");
596  break;
597  case ACK:
598 
599  if (cb == -1)
600  {
601  strcpy(DisplayCT[0].text, "Key press acknowledged");
602  strcpy(DisplayBT[0].text, DisplayCT[0].text);
603  strcpy(DisplayDT[0].text, DisplayCT[0].text);
604 
605  DisplayCTP.s = IPS_OK;
606  IDSetText(&DisplayCTP, NULL);
607  DisplayBTP.s = IPS_OK;
608  IDSetText(&DisplayBTP, NULL);
609  DisplayDTP.s = IPS_OK;
610  IDSetText(&DisplayDTP, NULL);
611  }
612  break;
613  case NACK:
614 
615  /*fprintf(stderr, "STV says NACK!!") ; */
616  IDMessage(mydev, "STV says NACK!");
617  break;
619 
620  IDMessage(mydev, "Request Buffer status seen, ignoring\n");
621  break;
622  default:
623 
624  if (guiding == ON)
625  { /* While STV is tracking, it send time, brightnes, centroid x,y */
626 
627  IDMessage(mydev, "Tracking: %s", tracking_buf);
628  }
629  else
630  {
631  /*fprintf(stderr, "STV ISCallBack: Unknown response 0x%2x\n", buf[1]) ; */
632  IDLog("ISCallBack: Unknown response 0x%2x\n", buf[1]);
633  }
634  break;
635  }
636  }
637  cb = IEAddCallback(fd, (IE_CBF *)ISCallBack, NULL);
638 }
639 
640 /* Client retrieves properties */
641 void ISGetProperties(const char *dev)
642 {
643  /* #1 Let's make sure everything has been initialized properly */
644  ISInit();
645  /* #2 Let's make sure that the client is asking for the properties of our device, otherwise ignore */
646  if (dev != nullptr && strcmp(mydev, dev))
647  return;
648 
649  /* #3 Tell the client to create new properties */
650 
651  /* Connection tab */
652 
653  IDDefText(&DisplayCTP, NULL);
654  IDDefSwitch(&PowerSP, NULL);
655  IDDefText(&PortTP, NULL);
656  IDDefSwitch(&TXDisplaySP, NULL);
657  IDDefText(&StatusTP, NULL);
658 
659  /* Settings Tab */
660  IDDefText(&UTCTP, NULL);
661  IDDefNumber(&SetCCDTemperatureNP, NULL);
662 
663  /* Buttons tab */
664  IDDefText(&DisplayBTP, NULL);
665  IDDefSwitch(&ControlSP, NULL);
666  IDDefSwitch(&ValueSP, NULL);
667  IDDefSwitch(&AuxiliarySP, NULL);
668  IDDefSwitch(&AcquireSP, NULL);
669  IDDefSwitch(&GuideSP, NULL);
670  IDDefSwitch(&ProcessSP, NULL);
671 
672  /* Image tab */
673  IDDefText(&DisplayDTP, NULL);
674  /* "direct" read out does not work well IDDefSwitch(&BufferStatusSP, NULL) ; */
675  IDDefSwitch(&BufferStatusSP, NULL);
676  IDDefSwitch(&ImageInfoSP, NULL);
677  IDDefNumber(&BufferNP, NULL);
678 
679  IDDefSwitch(&DownloadSP, NULL);
680  IDDefSwitch(&CompressionSP, NULL);
681  IDDefNumber(&WindowingNP, NULL);
682  IDDefBLOB(&imageBP, NULL);
683 }
684 
685 /* Client sets new switch */
686 void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
687 {
688  int i, j;
689  int res = 0;
690  int baud;
691  IMAGE_INFO image_info;
692  ISwitch *sp;
693  int lower_buffer = 0;
694  int upper_buffer = 0;
695 
696  /*fprintf(stderr, "ISNewSwitch\n") ; */
697 
698  /* #1 Let's make sure everything has been initialized properly */
699 
700  ISInit();
701 
702  /* #2 Let's make sure that the client is asking to update the properties of our device, otherwise ignore */
703 
704  if (dev != nullptr && strcmp(dev, mydev))
705  return;
706 
707  /* #3 Now let's check if the property the client wants to change is the PowerSP (name: CONNECTION) property*/
708 
709  if (!strcmp(name, PowerSP.name))
710  {
711  /* A. We reset all switches (in this case CONNECT and DISCONNECT) to ISS_OFF */
712 
714 
715  /* B. We update the switches by sending their names and updated states IUUpdateSwitch function */
716 
717  IUUpdateSwitch(&PowerSP, states, names, n);
718 
719  /* C. We try to establish a connection to our device or terminate it*/
720 
721  int res = 0;
722  switch (PowerS[0].s)
723  {
724  case ISS_ON:
725 
726  if ((res = strcmp("9600", PortT[1].text)) == 0)
727  {
728  baud = 9600;
729  }
730  else if ((res = strcmp("19200", PortT[1].text)) == 0)
731  {
732  baud = 19200;
733  }
734  else if ((res = strcmp("38400", PortT[1].text)) == 0)
735  {
736  baud = 38400;
737  }
738  else if ((res = strcmp("57600", PortT[1].text)) == 0)
739  {
740  baud = 57600;
741  }
742  else if ((res = strcmp("115200", PortT[1].text)) == 0)
743  {
744  baud = 115200;
745  }
746  else
747  {
748  IUSaveText(&PortT[1], "9600");
749  IDSetText(&PortTP, "Wrong RS 232 value: %s, defaulting to 9600 baud", PortT[1].text);
750  return;
751  }
752 
753  if ((fd = STV_Connect(PortT[0].text, baud)) == -1)
754  {
755  PowerSP.s = IPS_ALERT;
757  IDSetSwitch(&PowerSP, "Error connecting to port %s", PortT[0].text);
758 
759  return;
760  }
761  else
762  {
763  cb = IEAddCallback(fd, (IE_CBF *)ISCallBack, NULL);
764 
765  /* The SBIG manual says one can request an ACK, never saw it, even not on a RS 232 tester */
766  if ((res = STV_RequestAck()) != 0)
767  {
768  fprintf(stderr, "COULD not write an ACK\n");
769  }
770  /* Second trial: start reading out the display */
771  if ((res = STV_TXDisplay()) != 0)
772  {
773  fprintf(stderr, "STV: Could not write %d\n", res);
774  return;
775  }
776  }
777 
778  PowerSP.s = IPS_OK;
779  IDSetSwitch(&PowerSP, "STV is online, port: %s, baud rate: %s", PortT[0].text, PortT[1].text);
780 
781  PortTP.s = IPS_OK;
782  IDSetText(&PortTP, NULL);
783 
784  break;
785 
786  case ISS_OFF:
787 
788  IERmCallback(cb);
789  cb = -1;
790 
791  /* Close the serial port */
792 
794 
795  ISResetButtons(NULL);
796 
797  GuideSP.s = IPS_IDLE;
798  IUResetSwitch(&GuideSP);
799  IDSetSwitch(&GuideSP, NULL);
800 
801  TXDisplaySP.s = IPS_IDLE;
802  IUResetSwitch(&TXDisplaySP);
803  IDSetSwitch(&TXDisplaySP, NULL);
804 
805  DisplayCTP.s = IPS_IDLE;
806  IDSetText(&DisplayCTP, NULL);
807 
808  DisplayBTP.s = IPS_IDLE;
809  IDSetText(&DisplayBTP, NULL);
810 
811  DisplayDTP.s = IPS_IDLE;
812  IDSetText(&DisplayDTP, NULL);
813 
814  PortTP.s = IPS_IDLE;
815  IDSetText(&PortTP, NULL);
816 
817  imageB.blob = NULL;
818  imageB.bloblen = 0;
819  imageB.size = 0;
820 
821  imageBP.s = IPS_IDLE;
822  IDSetBLOB(&imageBP, NULL);
823 
824  PowerSP.s = IPS_IDLE;
826  IDSetSwitch(&PowerSP, "STV is offline");
827 
828  break;
829  }
830  return;
831  }
832  else if (!strcmp(name, AuxiliarySP.name))
833  {
834  /* Setup und interrupt buttons */
835 
836  ISResetButtons(NULL);
837  IUResetSwitch(&AuxiliarySP);
838  IUUpdateSwitch(&AuxiliarySP, states, names, n);
839 
840  for (i = 0; i < n; i++)
841  {
842  sp = IUFindSwitch(&AuxiliarySP, names[i]);
843 
844  if (sp == &AuxiliaryS[0])
845  {
846  res = STV_Setup();
847  }
848  else if (sp == &AuxiliaryS[1])
849  {
850  res = STV_Interrupt();
851  }
852  }
853  if (res == 0)
854  {
855  AuxiliarySP.s = IPS_OK;
856  IUResetSwitch(&AuxiliarySP);
857  IDSetSwitch(&AuxiliarySP, NULL);
858  }
859  else
860  {
861  AuxiliarySP.s = IPS_ALERT;
862  IUResetSwitch(&AuxiliarySP);
863  IDSetSwitch(&AuxiliarySP, "Check connection");
864  }
865  }
866  else if (!strcmp(name, ControlSP.name))
867  {
868  /* Parameter, value and the rotary knobs */
869  ISResetButtons(NULL);
870  IUResetSwitch(&ControlSP);
871  IUUpdateSwitch(&ControlSP, states, names, n);
872 
873  acquiring = OFF;
874  guiding = OFF;
875  processing = OFF;
876 
877  for (i = 0; i < n; i++)
878  {
879  sp = IUFindSwitch(&ControlSP, names[i]);
880 
881  /* If the state found is ControlS[0] then process it */
882 
883  if (sp == &ControlS[0])
884  {
885  res = STV_AKey();
886  }
887  else if (sp == &ControlS[1])
888  {
889  res = STV_UDRotaryIncrease();
890  }
891  else if (sp == &ControlS[2])
892  {
893  res = STV_UDRotaryDecrease();
894  }
895  }
896  if (res == 0)
897  {
898  ControlSP.s = IPS_OK;
899  IUResetSwitch(&ControlSP);
900  IDSetSwitch(&ControlSP, NULL);
901  }
902  else
903  {
904  ControlSP.s = IPS_ALERT;
905  IUResetSwitch(&ControlSP);
906  IDSetSwitch(&ControlSP, "Check connection");
907  }
908  }
909  else if (!strcmp(name, ValueSP.name))
910  {
911  /* Button Value, left/right knob */
912  ISResetButtons(NULL);
913  IUResetSwitch(&ValueSP);
914  IUUpdateSwitch(&ValueSP, states, names, n);
915 
916  acquiring = OFF;
917  guiding = OFF;
918  processing = OFF;
919 
920  for (i = 0; i < n; i++)
921  {
922  sp = IUFindSwitch(&ValueSP, names[i]);
923 
924  if (sp == &ValueS[0])
925  {
926  res = STV_BKey();
927  }
928  else if (sp == &ValueS[1])
929  {
930  res = STV_LRRotaryIncrease();
931  }
932  else if (sp == &ValueS[2])
933  {
934  res = STV_LRRotaryDecrease();
935  }
936  }
937 
938  if (res == 0)
939  {
940  ValueSP.s = IPS_OK;
941  IUResetSwitch(&ValueSP);
942  IDSetSwitch(&ValueSP, NULL);
943  }
944  else
945  {
946  ValueSP.s = IPS_ALERT;
947  IUResetSwitch(&ValueSP);
948  IDSetSwitch(&ValueSP, "Check connection");
949  }
950  }
951  else if (!strcmp(name, AcquireSP.name))
952  {
953  /* Focus, Image Monitor buttons */
954  ISResetButtons(NULL);
955  IUResetSwitch(&AcquireSP);
956  IUUpdateSwitch(&AcquireSP, states, names, n);
957 
958  acquiring = ON;
959  guiding = OFF;
960  processing = OFF;
961 
962  for (i = 0; i < n; i++)
963  {
964  sp = IUFindSwitch(&AcquireSP, names[i]);
965 
966  if (sp == &AcquireS[0])
967  {
968  res = STV_Focus();
969  }
970  else if (sp == &AcquireS[1])
971  {
972  res = STV_Image();
973  }
974  else if (sp == &AcquireS[2])
975  {
976  res = STV_Monitor();
977  }
978  }
979  if (res == 0)
980  {
981  AcquireSP.s = IPS_OK;
982  IUResetSwitch(&AcquireSP);
983  IDSetSwitch(&AcquireSP, NULL);
984  }
985  else
986  {
987  AcquireSP.s = IPS_ALERT;
988  IUResetSwitch(&AcquireSP);
989  IDSetSwitch(&AcquireSP, "Check connection");
990  }
991  }
992  else if (!strcmp(name, GuideSP.name))
993  {
994  /* Calibrate, Track buttons */
995  ISResetButtons(NULL);
996  IUResetSwitch(&GuideSP);
997  IUUpdateSwitch(&GuideSP, states, names, n);
998 
999  acquiring = OFF;
1000  guiding = ON;
1001  processing = OFF;
1002 
1003  for (i = 0; i < n; i++)
1004  {
1005  sp = IUFindSwitch(&GuideSP, names[i]);
1006 
1007  if (sp == &GuideS[0])
1008  {
1009  res = STV_Calibrate();
1010  }
1011  else if (sp == &GuideS[1])
1012  {
1013  res = STV_Track();
1014  }
1015  }
1016  if (res == 0)
1017  {
1018  GuideSP.s = IPS_OK;
1019  IUResetSwitch(&GuideSP);
1020  IDSetSwitch(&GuideSP, NULL);
1021  }
1022  else
1023  {
1024  GuideSP.s = IPS_ALERT;
1025  IUResetSwitch(&GuideSP);
1026  IDSetSwitch(&GuideSP, "Check connection");
1027  }
1028  }
1029  else if (!strcmp(name, ProcessSP.name))
1030  {
1031  ISResetButtons(NULL);
1032  IUResetSwitch(&ProcessSP);
1033  IUUpdateSwitch(&ProcessSP, states, names, n);
1034 
1035  acquiring = OFF;
1036  guiding = OFF;
1037  processing = ON;
1038 
1039  for (i = 0; i < n; i++)
1040  {
1041  sp = IUFindSwitch(&ProcessSP, names[i]);
1042 
1043  if (sp == &ProcessS[0])
1044  {
1045  res = STV_Display();
1046  }
1047  else if (sp == &ProcessS[1])
1048  {
1049  res = STV_FileOps();
1050  }
1051  }
1052  if (res == 0)
1053  {
1054  ProcessSP.s = IPS_OK;
1055  IUResetSwitch(&ProcessSP);
1056  IDSetSwitch(&ProcessSP, NULL);
1057  }
1058  else
1059  {
1060  ProcessSP.s = IPS_ALERT;
1061  IUResetSwitch(&ProcessSP);
1062  IDSetSwitch(&ProcessSP, "Check connection");
1063  }
1064  }
1065  else if (!strcmp(name, ImageInfoSP.name))
1066  {
1067  acquiring = OFF;
1068  guiding = OFF;
1069  processing = OFF;
1070 
1071  /* Read out the image buffer and display a short message if it is empty or not */
1072  res = ISTerminateTXDisplay();
1073 
1074  for (i = 0; i < n; i++)
1075  {
1076  sp = IUFindSwitch(&ImageInfoSP, names[i]);
1077 
1078  if (sp == &ImageInfoS[0])
1079  {
1080  if ((res = STV_RequestImageInfo(currentBuffer - 1, &image_info)) == 0)
1081  {
1082  ISMessageImageInfo((int)currentBuffer - 1, &image_info);
1083  }
1084  else
1085  {
1086  IDMessage(mydev, "Buffer %2d is empty", (int)currentBuffer);
1087  }
1088  break;
1089  }
1090  else if (sp == &ImageInfoS[1])
1091  {
1092  for (i = 0; i < 32; i++)
1093  {
1094  if ((res = STV_RequestImageInfo(i, &image_info)) == 0)
1095  {
1096  ISMessageImageInfo(i, &image_info);
1097  }
1098  else
1099  {
1100  IDMessage(mydev, "Buffer %2d is empty", i + 1);
1101  }
1102  }
1103  break;
1104  }
1105  }
1106  if (res == 0)
1107  {
1108  ImageInfoSP.s = IPS_OK;
1109  IUResetSwitch(&ImageInfoSP);
1110  IDSetSwitch(&ImageInfoSP, NULL);
1111  }
1112  else
1113  {
1114  ImageInfoSP.s = IPS_ALERT;
1115  IUResetSwitch(&ImageInfoSP);
1116  /*IDSetSwitch( &ImageInfoSP, "Check connection") ; */
1117  IDSetSwitch(&ImageInfoSP, NULL);
1118  }
1119  res = STV_Interrupt(); /* STV initiates a download that we do not want */
1120  res = ISRestoreTXDisplay();
1121  }
1122  else if (!strcmp(name, CompressionSP.name))
1123  {
1124  acquiring = OFF;
1125  guiding = OFF;
1126  processing = OFF;
1127 
1128  /* Enable or disable compression for image download */
1129  ISResetButtons(NULL);
1130  IUResetSwitch(&CompressionSP);
1131  IUUpdateSwitch(&CompressionSP, states, names, n);
1132 
1133  for (i = 0; i < n; i++)
1134  {
1135  sp = IUFindSwitch(&CompressionSP, names[i]);
1136 
1137  if (sp == &CompressionS[0])
1138  {
1139  CompressionS[0].s = ISS_ON;
1140  }
1141  else if (sp == &CompressionS[1])
1142  {
1143  CompressionS[1].s = ISS_ON;
1144  }
1145  }
1146 
1147  CompressionSP.s = IPS_OK;
1148  IDSetSwitch(&CompressionSP, NULL);
1149  }
1150  else if (!strcmp(name, BufferStatusSP.name))
1151  {
1152  ISResetButtons(NULL);
1153 
1154  BufferStatusSP.s = IPS_ALERT;
1155  IUResetSwitch(&BufferStatusSP);
1156  IDSetSwitch(&BufferStatusSP, "Wait...");
1157 
1158  if ((AcquireSP.s != OFF) || (GuideSP.s != OFF) || (ProcessSP.s != OFF))
1159  {
1160  acquiring = OFF;
1161  guiding = OFF;
1162  processing = OFF;
1163 
1164  ISResetButtons("Interrupting ongoing image acquisition, calibration or tracking\n");
1165 
1166  AcquireSP.s = IPS_IDLE;
1167  IUResetSwitch(&AcquireSP);
1168  IDSetSwitch(&AcquireSP, NULL);
1169 
1170  GuideSP.s = IPS_IDLE;
1171  IUResetSwitch(&GuideSP);
1172  IDSetSwitch(&GuideSP, NULL);
1173 
1174  ProcessSP.s = IPS_IDLE;
1175  IUResetSwitch(&ProcessSP);
1176  IDSetSwitch(&ProcessSP, NULL);
1177 
1178  ImageInfoSP.s = IPS_IDLE;
1179  IUResetSwitch(&ImageInfoSP);
1180  IDSetSwitch(&ImageInfoSP, NULL);
1181 
1182  res = STV_Interrupt();
1183  usleep(100000);
1184  res = STV_Interrupt();
1185  }
1186  acquiring = OFF;
1187  guiding = OFF;
1188  processing = OFF;
1189 
1190  sp = IUFindSwitch(&BufferStatusSP, names[0]);
1191 
1192  if ((res = ISTerminateTXDisplay()) != 0)
1193  {
1194  fprintf(stderr, "STV Buffer can not terminate TX %d\n", res);
1195  }
1196 
1197  if (sp == &BufferStatusS[0])
1198  {
1199  for (i = 31; i > -1; i--)
1200  {
1201  usleep(50000);
1202  if ((res = STV_BufferStatus(i)) == 0)
1203  {
1204  IDMessage(mydev, "Buffer %2d: image present", i + 1);
1205  }
1206  else
1207  {
1208  IDMessage(mydev, "Buffer %2d: empty", i + 1);
1209  }
1210  }
1211  }
1212 
1213  BufferStatusS[0].s = ISS_OFF;
1214 
1215  if (0 <= res)
1216  {
1217  BufferStatusSP.s = IPS_OK;
1218  IUResetSwitch(&BufferStatusSP);
1219  IDSetSwitch(&BufferStatusSP, NULL);
1220  }
1221  else
1222  {
1223  BufferStatusSP.s = IPS_ALERT;
1224  IUResetSwitch(&BufferStatusSP);
1225  IDSetSwitch(&BufferStatusSP, "Check connection");
1226  }
1227 
1228  res = ISRestoreTXDisplay();
1229  res = STV_Interrupt();
1230  }
1231  else if (!strcmp(name, DownloadSP.name))
1232  {
1233  /* Download images */
1234  /* Downloading while the STV is occupied is not working */
1235  if ((AcquireSP.s != OFF) || (GuideSP.s != OFF) || (ProcessSP.s != OFF))
1236  {
1237  ISResetButtons("Interrupting ongoing image acquisition, calibration or tracking\n");
1238 
1239  AcquireSP.s = IPS_IDLE;
1240  IUResetSwitch(&AcquireSP);
1241  IDSetSwitch(&AcquireSP, NULL);
1242 
1243  GuideSP.s = IPS_IDLE;
1244  IUResetSwitch(&GuideSP);
1245  IDSetSwitch(&GuideSP, NULL);
1246 
1247  ProcessSP.s = IPS_IDLE;
1248  IUResetSwitch(&ProcessSP);
1249  IDSetSwitch(&ProcessSP, NULL);
1250 
1251  ImageInfoSP.s = IPS_IDLE;
1252  IUResetSwitch(&ImageInfoSP);
1253  IDSetSwitch(&ImageInfoSP, NULL);
1254 
1255  res = STV_Interrupt();
1256  usleep(100000);
1257  res = STV_Interrupt();
1258  }
1259  acquiring = OFF;
1260  guiding = OFF;
1261  processing = OFF;
1262 
1263  if ((res = ISTerminateTXDisplay()) != 0)
1264  {
1265  fprintf(stderr, "STV Buffer can not terminate TX %d\n", res);
1266  }
1267 
1268  DownloadSP.s = IPS_ALERT;
1269  IUResetSwitch(&DownloadSP);
1270  IDSetSwitch(&DownloadSP, NULL);
1271 
1272  compression = OFF;
1273  if (CompressionS[0].s == ISS_ON)
1274  {
1275  compression = ON;
1276  }
1277  for (i = 0; i < n; i++)
1278  {
1279  sp = IUFindSwitch(&DownloadSP, names[i]);
1280 
1281  if (sp == &DownloadS[0])
1282  {
1283  lower_buffer = currentBuffer - 2;
1284  upper_buffer = currentBuffer - 1;
1285  }
1286  else if (sp == &DownloadS[1])
1287  {
1288  lower_buffer = -1;
1289  upper_buffer = 31;
1290  }
1291  }
1292  for (j = upper_buffer; j > lower_buffer; j--)
1293  {
1294  if ((res = ISRequestImageData(compression, j, currentX, currentY, currentLength, currentLines)) != 0)
1295  {
1296  if (res == 1)
1297  {
1298  IDMessage(mydev, "Buffer %2.0f: empty", (double)(j + 1));
1299  }
1300  else
1301  {
1302  break;
1303  }
1304  }
1305  }
1306  if (res == 0)
1307  {
1308  IDMessage(mydev, "STV waits for SYNC TIME Do it! Setting time, PLEASE WAIT!");
1309 
1310  if ((res = STV_SetDateTime(NULL)) == 0)
1311  {
1312  UTCTP.s = IPS_OK;
1313  IDSetText(&UTCTP, "Time set to UTC now");
1314  }
1315  else
1316  {
1317  UTCTP.s = IPS_ALERT;
1318  IDSetText(&UTCTP, "Error setting time, check connection");
1319  }
1320 
1321  DownloadSP.s = IPS_OK;
1322  IUResetSwitch(&DownloadSP);
1323  IDSetSwitch(&DownloadSP, NULL);
1324  }
1325  else
1326  { /* res could be -1 (STV_RequestImageData) */
1327 
1328  DownloadSP.s = IPS_ALERT;
1329  IUResetSwitch(&DownloadSP);
1330  IDSetSwitch(&DownloadSP, "Check connection");
1331  IDSetSwitch(&DownloadSP, NULL);
1332  }
1333 
1334  res = ISRestoreTXDisplay();
1335  res = STV_Interrupt();
1336  IDMessage(mydev, "You may continue NOW");
1337  }
1338  else if (!strcmp(name, TXDisplaySP.name))
1339  {
1340  acquiring = OFF;
1341  guiding = OFF;
1342  processing = OFF;
1343 
1344  ISResetButtons(NULL);
1345  IUResetSwitch(&TXDisplaySP);
1346  IUUpdateSwitch(&TXDisplaySP, states, names, n);
1347 
1348  for (i = 0; i < n; i++)
1349  {
1350  sp = IUFindSwitch(&TXDisplaySP, names[i]);
1351 
1352  if (sp == &TXDisplayS[0])
1353  {
1354  if ((res = STV_TXDisplay()) == 0)
1355  {
1356  TXDisplaySP.s = IPS_OK;
1357  IDSetSwitch(&TXDisplaySP, "Reading out display");
1358 
1359  DisplayCTP.s = IPS_OK;
1360  IDSetText(&DisplayCTP, NULL);
1361 
1362  DisplayBTP.s = IPS_OK;
1363  IDSetText(&DisplayBTP, NULL);
1364 
1365  DisplayDTP.s = IPS_OK;
1366  IDSetText(&DisplayDTP, NULL);
1367  }
1368  }
1369  else if (sp == &TXDisplayS[1])
1370  {
1371  DisplayCTP.s = IPS_IDLE;
1372  DisplayBTP.s = IPS_IDLE;
1373  DisplayDTP.s = IPS_IDLE;
1374 
1375  if ((res = STV_TerminateTXDisplay()) == 0)
1376  {
1377  TXDisplaySP.s = IPS_OK;
1378  IDSetSwitch(&TXDisplaySP, "Stopping display read out");
1379 
1380  DisplayCTP.s = IPS_IDLE;
1381  IUSaveText(&DisplayCT[0], " "); /* reset client's display */
1382  IUSaveText(&DisplayCT[1], " ");
1383  IDSetText(&DisplayCTP, NULL);
1384 
1385  DisplayBTP.s = IPS_IDLE;
1386  IUSaveText(&DisplayBT[0], " "); /* reset client's display */
1387  IUSaveText(&DisplayBT[1], " ");
1388  IDSetText(&DisplayBTP, NULL);
1389 
1390  DisplayDTP.s = IPS_IDLE;
1391  IUSaveText(&DisplayDT[0], " "); /* reset client's display */
1392  IUSaveText(&DisplayDT[1], " ");
1393  IDSetText(&DisplayDTP, NULL);
1394  }
1395  }
1396  }
1397  if (res != 0)
1398  {
1399  TXDisplaySP.s = IPS_ALERT;
1400  IUResetSwitch(&TXDisplaySP);
1401  IDSetSwitch(&TXDisplaySP, "Check connection");
1402  }
1403  }
1404 }
1405 
1406 void ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
1407 {
1408  int res;
1409  IText *tp;
1410 
1411  /*fprintf(stderr, "ISNewText\n") ; */
1412 
1413  /* #1 Let's make sure everything has been initialized properly */
1414  ISInit();
1415 
1416  /* #2 Let's make sure that the client is asking to update the properties of our device, otherwise ignore */
1417  if (dev != nullptr && strcmp(dev, mydev))
1418  return;
1419 
1420  if (!strcmp(name, PortTP.name))
1421  {
1422  if (IUUpdateText(&PortTP, texts, names, n) < 0)
1423  return;
1424 
1425  PortTP.s = IPS_OK;
1426 
1427  if (PowerS[0].s == ISS_ON)
1428  {
1429  PortTP.s = IPS_ALERT;
1430  IDSetText(&PortTP, "STV is already online");
1431  }
1432 
1433  /* JM: Don't forget to send acknowledgment */
1434  IDSetText(&PortTP, NULL);
1435  }
1436  else if (!strcmp(name, UTCTP.name))
1437  {
1438  ISResetButtons(NULL);
1439 
1440  tp = IUFindText(&UTCTP, names[0]);
1441 
1442  if ((res = ISTerminateTXDisplay()) != 0)
1443  {
1444  fprintf(stderr, "STV Buffer can not terminate TX %d\n", res);
1445  }
1446 
1447  if (tp == &UTCT[0])
1448  {
1449  if ((res = STV_SetDateTime(NULL)) == 0)
1450  {
1451  UTCTP.s = IPS_OK;
1452  IDSetText(&UTCTP, "Time set to UTC");
1453  }
1454  else
1455  {
1456  UTCTP.s = IPS_ALERT;
1457  IDSetText(&UTCTP, "Error setting time, check connection");
1458  }
1459  }
1460  res = ISRestoreTXDisplay();
1461  }
1462 }
1463 /* Client sets new number */
1464 void ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
1465 {
1466  int res;
1467  double ccd_temperature;
1468  /*fprintf(stderr, "ISNewNumber\n") ; */
1469 
1470  /* #1 Let's make sure everything has been initialized properly */
1471  ISInit();
1472 
1473  /* #2 Let's make sure that the client is asking to update the properties of our device, otherwise ignore */
1474  if (dev != nullptr && strcmp(dev, mydev))
1475  return;
1476 
1477  if (PowerS[0].s != ISS_ON)
1478  {
1479  PowerSP.s = IPS_ALERT;
1480  IDSetSwitch(&PowerSP, NULL);
1481  IDMessage("STV is offline", NULL);
1482  return;
1483  }
1484 
1485  if (!strcmp(name, BufferNP.name))
1486  {
1487  INumber *buffer = IUFindNumber(&BufferNP, names[0]);
1488 
1489  if (buffer == &BufferN[0])
1490  {
1491  currentBuffer = values[0];
1492 
1493  /* Check the boundaries, this is incomplete at the moment */
1494  BufferNP.s = IPS_OK;
1495  IDSetNumber(&BufferNP, NULL);
1496  }
1497  }
1498  else if (!strcmp(name, WindowingNP.name))
1499  {
1500  INumber *buffer = IUFindNumber(&WindowingNP, names[0]);
1501 
1502  if (buffer == &WindowingN[0])
1503  {
1504  currentX = values[0];
1505  currentY = values[1];
1506  currentLines = values[2];
1507  currentLength = values[3];
1508 
1509  WindowingNP.s = IPS_OK;
1510  IDSetNumber(&WindowingNP, NULL);
1511  }
1512  }
1513  else if (!strcmp(name, SetCCDTemperatureNP.name))
1514  {
1515  if ((res = ISTerminateTXDisplay()) != 0)
1516  {
1517  fprintf(stderr, "STV Buffer can not terminate TX %d\n", res);
1518  }
1519 
1520  INumber *np = IUFindNumber(&SetCCDTemperatureNP, names[0]);
1521 
1522  if (np == &SetCCDTemperatureN[0])
1523  {
1524  if ((ccd_temperature = STV_SetCCDTemperature(values[0])) != 0)
1525  { /* STV has no 0 C setting */
1526 
1527  SetCCDTemperatureNP.s = IPS_OK;
1528  SetCCDTemperatureN[0].value = ccd_temperature;
1529  IDSetNumber(&SetCCDTemperatureNP, "CCD Temperature set to %g", SetCCDTemperatureN[0].value);
1530  }
1531  else
1532  {
1533  SetCCDTemperatureNP.s = IPS_ALERT;
1534  IDSetNumber(&SetCCDTemperatureNP, "Error setting CCD temperature, check connection");
1535  }
1536  }
1537  res = ISRestoreTXDisplay();
1538  }
1539 }
1540 
1541 void ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[],
1542  char *names[], int n)
1543 {
1544  INDI_UNUSED(dev);
1545  INDI_UNUSED(name);
1546  INDI_UNUSED(sizes);
1547  INDI_UNUSED(blobsizes);
1548  INDI_UNUSED(blobs);
1549  INDI_UNUSED(formats);
1550  INDI_UNUSED(names);
1551  INDI_UNUSED(n);
1552 }
1554 {
1555  INDI_UNUSED(root);
1556 }
1557 
1558 int writeFITS(const char *filename, IMAGE_INFO *image_info, char errmsg[])
1559 {
1560  fitsfile *fptr; /* pointer to the FITS file; defined in fitsio.h */
1561  int status;
1562  long fpixel = 1, naxis = 2, nelements;
1563  long naxes[2];
1564  char filename_rw[TEMPFILE_LEN + 1];
1565 
1566  naxes[0] = STVImg->width;
1567  naxes[1] = STVImg->height;
1568 
1569  /* Append ! to file name to over write it.*/
1570  snprintf(filename_rw, TEMPFILE_LEN + 1, "!%s", filename);
1571 
1572  status = 0; /* initialize status before calling fitsio routines */
1573  fits_create_file(&fptr, filename_rw, &status); /* create new file */
1574 
1575  /* Create the primary array image (16-bit short integer pixels */
1576  fits_create_img(fptr, USHORT_IMG, naxis, naxes, &status);
1577 
1578  addFITSKeywords(fptr, image_info);
1579 
1580  nelements = naxes[0] * naxes[1]; /* number of pixels to write */
1581 
1582  /* Write the array of integers to the image */
1583  fits_write_img(fptr, TUSHORT, fpixel, nelements, STVImg->img, &status);
1584 
1585  fits_close_file(fptr, &status); /* close the file */
1586 
1587  fits_report_error(stderr, status); /* print out any error messages */
1588 
1589  /* Success */
1590  /*ExposeTimeNP.s = IPS_OK; */
1591  /*IDSetNumber(&ExposeTimeNP, NULL); */
1592  uploadFile(filename);
1593 
1594  return status;
1595 }
1596 
1597 void addFITSKeywords(fitsfile *fptr, IMAGE_INFO *image_info)
1598 {
1599  int status = 0;
1600  char binning_s[32];
1601  char frame_s[32];
1602  char date_obs_s[64];
1603  char tmp[32];
1604 
1605  image_info->pixelSize = 7.4; /* microns */
1606 
1607  if (image_info->binning == 1)
1608  {
1609  snprintf(binning_s, 32, "(%1.0f x %1.0f)", 1., 1.);
1610  }
1611  else if (image_info->binning == 2)
1612  {
1613  snprintf(binning_s, 32, "(%1.0f x %1.0f)", 2., 2.);
1614  }
1615  else if (image_info->binning == 3)
1616  {
1617  snprintf(binning_s, 32, "(%1.0f x %1.0f)", 3., 3.);
1618  }
1619  else
1620  {
1621  fprintf(stderr, "Error in binning information: %d\n", image_info->binning);
1622  }
1623 
1624  strcpy(frame_s, "Light");
1625 
1626  /* ToDo: assign the frame type */
1627  /* switch (STVImg->frameType) */
1628  /* { */
1629  /* case LIGHT_FRAME: */
1630  /* strcpy(frame_s, "Light"); */
1631  /* break; */
1632  /* case BIAS_FRAME: */
1633  /* strcpy(frame_s, "Bias"); */
1634  /* break; */
1635  /* case FLAT_FRAME: */
1636  /* strcpy(frame_s, "Flat Field"); */
1637  /* break; */
1638  /* case DARK_FRAME: */
1639  /* strcpy(frame_s, "Dark"); */
1640  /* break; */
1641  /* } */
1642 
1643  fits_update_key(fptr, TDOUBLE, "CCD-TEMP", &(image_info->ccdTemp), "CCD Temperature (Celcius)", &status);
1644  fits_update_key(fptr, TDOUBLE, "EXPOSURE", &(image_info->exposure), "Total Exposure Time (ms)", &status);
1645  fits_update_key(fptr, TDOUBLE, "PIX-SIZ", &(image_info->pixelSize), "Pixel Size (microns)", &status);
1646  fits_update_key(fptr, TSTRING, "BINNING", binning_s, "Binning HOR x VER", &status);
1647  fits_update_key(fptr, TSTRING, "FRAME", frame_s, "Frame Type", &status);
1648  fits_update_key(fptr, TDOUBLE, "DATAMIN", &(image_info->minValue), "Minimum value", &status);
1649  fits_update_key(fptr, TDOUBLE, "DATAMAX", &(image_info->maxValue), "Maximum value", &status);
1650  fits_update_key(fptr, TSTRING, "INSTRUME", "SBIG STV", "CCD Name", &status);
1651 
1652  sprintf(tmp, "%4d-", image_info->year);
1653  strcpy(date_obs_s, tmp);
1654 
1655  if (image_info->month < 10)
1656  {
1657  sprintf(tmp, "0%1d-", image_info->month);
1658  }
1659  else
1660  {
1661  sprintf(tmp, "%2d-", image_info->month);
1662  }
1663  strcat(date_obs_s, tmp);
1664 
1665  if (image_info->day < 10)
1666  {
1667  sprintf(tmp, "0%1dT", image_info->day);
1668  }
1669  else
1670  {
1671  sprintf(tmp, "%2dT", image_info->day);
1672  }
1673  strcat(date_obs_s, tmp);
1674 
1675  if (image_info->hours < 10)
1676  {
1677  sprintf(tmp, "0%1d:", image_info->hours);
1678  }
1679  else
1680  {
1681  sprintf(tmp, "%2d:", image_info->hours);
1682  }
1683  strcat(date_obs_s, tmp);
1684 
1685  if (image_info->minutes < 10)
1686  {
1687  sprintf(tmp, "0%1d:", image_info->minutes);
1688  }
1689  else
1690  {
1691  sprintf(tmp, "%2d:", image_info->minutes);
1692  }
1693  strcat(date_obs_s, tmp);
1694 
1695  if (image_info->seconds < 10)
1696  {
1697  sprintf(tmp, "0%1d:", image_info->seconds);
1698  }
1699  else
1700  {
1701  sprintf(tmp, "%2d:", image_info->seconds);
1702  }
1703  strcat(date_obs_s, tmp);
1704 
1705  fits_update_key(fptr, TSTRING, "DATE-OBS", date_obs_s, "Observing date (YYYY-MM-DDThh:mm:ss UT", &status);
1706 
1707  fits_write_date(fptr, &status);
1708 }
1709 
1710 void uploadFile(const char *filename)
1711 {
1712  FILE *fitsFile;
1713  unsigned char *fitsData, *compressedData;
1714  int r = 0;
1715  unsigned int i = 0, nr = 0;
1716  uLongf compressedBytes = 0;
1717  uLong totalBytes;
1718  struct stat stat_p;
1719 
1720  if (-1 == stat(filename, &stat_p))
1721  {
1722  IDLog("Error occurred attempting to stat file.\n");
1723  return;
1724  }
1725 
1726  totalBytes = stat_p.st_size;
1727 
1728  fitsData = (unsigned char *)malloc(sizeof(unsigned char) * totalBytes);
1729  compressedData = (unsigned char *)malloc(sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
1730 
1731  if (fitsData == NULL || compressedData == NULL)
1732  {
1733  if (fitsData)
1734  free(fitsData);
1735  if (compressedData)
1736  free(compressedData);
1737  IDLog("Error! low memory. Unable to initialize fits buffers.\n");
1738  return;
1739  }
1740 
1741  fitsFile = fopen(filename, "r");
1742 
1743  if (fitsFile == NULL)
1744  {
1745  free(fitsData);
1746  free(compressedData);
1747  return;
1748  }
1749 
1750  /* #1 Read file from disk */
1751  for (i = 0; i < totalBytes; i += nr)
1752  {
1753  nr = fread(fitsData + i, 1, totalBytes - i, fitsFile);
1754 
1755  if (nr <= 0)
1756  {
1757  IDLog("Error reading temporary FITS file.\n");
1758  free(fitsData);
1759  fclose(fitsFile);
1760  return;
1761  }
1762  }
1763  fclose(fitsFile);
1764 
1765  compressedBytes = sizeof(char) * totalBytes + totalBytes / 64 + 16 + 3;
1766 
1767  /* #2 Compress it */
1768  r = compress2(compressedData, &compressedBytes, fitsData, totalBytes, 9);
1769  if (r != Z_OK)
1770  {
1771  /* this should NEVER happen */
1772  IDLog("internal error - compression failed: %d\n", r);
1773  return;
1774  }
1775 
1776  /* #3 Send it */
1777  imageB.blob = compressedData;
1778  imageB.bloblen = compressedBytes;
1779  imageB.size = totalBytes;
1780  strcpy(imageB.format, ".fits.z");
1781 
1782  imageBP.s = IPS_OK;
1783  IDSetBLOB(&imageBP, NULL);
1784 
1785  free(fitsData);
1786  free(compressedData);
1787 }
1788 
1790 {
1791  int res = 0;
1792  res = STV_Interrupt(); /* with out it hangs */
1793  usleep(100000);
1794 
1795  IERmCallback(cb);
1796  cb = -1;
1797 
1798  if (TXDisplayS[0].s == ISS_ON)
1799  {
1800  TXDisplaySP.s = IPS_BUSY;
1801  IDSetSwitch(&TXDisplaySP, "Stopping display read out");
1802 
1803  DisplayCTP.s = IPS_IDLE;
1804  IUSaveText(&DisplayCT[0], " "); /* reset client's display */
1805  IUSaveText(&DisplayCT[1], " ");
1806  IDSetText(&DisplayCTP, NULL);
1807 
1808  DisplayBTP.s = IPS_IDLE;
1809  IUSaveText(&DisplayBT[0], " "); /* reset client's display */
1810  IUSaveText(&DisplayBT[1], " ");
1811  IDSetText(&DisplayBTP, NULL);
1812 
1813  DisplayDTP.s = IPS_IDLE;
1814  IUSaveText(&DisplayDT[0], " "); /* reset client's display */
1815  IUSaveText(&DisplayDT[1], " ");
1816  IDSetText(&DisplayDTP, NULL);
1817 
1818  if ((res = STV_TerminateTXDisplay()) != 0)
1819  {
1820  fprintf(stderr, "STV: error writing TTXD %d\n", res);
1821  }
1822  }
1823  else
1824  {
1825  res = 0;
1826  }
1827  usleep(500000); /* make sure that everything is discarded */
1828  tcflush(fd, TCIOFLUSH);
1829 
1830  return res;
1831 }
1832 
1834 {
1835  int res = 0;
1836 
1837  cb = IEAddCallback(fd, (IE_CBF *)ISCallBack, NULL);
1838 
1839  if (TXDisplayS[0].s == ISS_ON)
1840  {
1841  usleep(500000); /* STV need a little rest */
1842  res = STV_TXDisplay();
1843 
1844  TXDisplaySP.s = IPS_OK;
1845  IDSetSwitch(&TXDisplaySP, "Starting Display read out");
1846 
1847  DisplayCTP.s = IPS_OK;
1848  IDSetText(&DisplayCTP, NULL);
1849 
1850  DisplayBTP.s = IPS_OK;
1851  IDSetText(&DisplayBTP, NULL);
1852 
1853  DisplayDTP.s = IPS_OK;
1854  IDSetText(&DisplayDTP, NULL);
1855  }
1856  return res;
1857 }
1858 
1859 int ISMessageImageInfo(int buffer, IMAGE_INFO *image_info)
1860 {
1861  buffer++;
1862 
1863  /* IDMessage( mydev, "B%2d: descriptor:%d\n", buffer, image_info->descriptor) ; */
1864  /* IDMessage( mydev, "B%2d: height:%d\n", buffer, image_info->height) ; */
1865  /* IDMessage( mydev, "B%2d: width:%d\n", buffer, image_info->width) ; */
1866  /* IDMessage( mydev, "B%2d: top:%d\n", buffer, image_info->top) ; */
1867  /* IDMessage( mydev, "B%2d: left:%d\n", buffer, image_info->left) ; */
1868  IDMessage(mydev, "B%2d: Exposure:%6.3f, Height:%2d, Width:%2d, CCD Temperature:%3.1f\n", buffer,
1869  image_info->exposure, image_info->height, image_info->width, image_info->ccdTemp);
1870  /* IDMessage( mydev, "B%2d: noExposure:%d\n", buffer, image_info->noExposure) ; */
1871  /* IDMessage( mydev, "B%2d: analogGain:%d\n", buffer, image_info->analogGain) ; */
1872  /* IDMessage( mydev, "B%2d: digitalGain:%d\n", buffer, image_info->digitalGain) ; */
1873  /* IDMessage( mydev, "B%2d: focalLength:%d\n", buffer, image_info->focalLength) ; */
1874  /* IDMessage( mydev, "B%2d: aperture:%d\n", buffer, image_info->aperture) ; */
1875  /* IDMessage( mydev, "B%2d: packedDate:%d\n", buffer, image_info->packedDate) ; */
1876  IDMessage(mydev, "B%2d: Year:%4d, Month: %2d, Day:%2d\n", buffer, image_info->year, image_info->month,
1877  image_info->day);
1878  /* IDMessage( mydev, "B%2d: Day:%d\n", buffer, image_info->day) ; */
1879  /* IDMessage( mydev, "B%2d: Month:%d\n", buffer, image_info->month) ; */
1880  /* IDMessage( mydev, "B%2d: packedTime:%d\n", buffer, image_info->packedTime) ; */
1881  /* IDMessage( mydev, "B%2d: Seconds:%d\n", buffer, image_info->seconds) ; */
1882  /* IDMessage( mydev, "B%2d: minutes:%d\n", buffer, image_info->minutes) ; */
1883  IDMessage(mydev, "B%2d: Hours:%2d, Minutes:%2d, Seconds:%d\n", buffer, image_info->hours, image_info->minutes,
1884  image_info->seconds);
1885 
1886  /* IDMessage( mydev, "B%2d: ccdTemp:%f\n", buffer, image_info->ccdTemp) ; */
1887  /* IDMessage( mydev, "B%2d: siteID:%d\n", buffer, image_info->siteID) ; */
1888  /* IDMessage( mydev, "B%2d: eGain:%d\n", buffer, image_info->eGain) ; */
1889  /* IDMessage( mydev, "B%2d: background:%d\n", buffer, image_info->background) ; */
1890  /* IDMessage( mydev, "B%2d: range :%d\n", buffer, image_info->range ) ; */
1891  /* IDMessage( mydev, "B%2d: pedestal:%d\n", buffer, image_info->pedestal) ; */
1892  /* IDMessage( mydev, "B%2d: ccdTop :%d\n", buffer, image_info->ccdTop) ; */
1893  /* IDMessage( mydev, "B%2d: ccdLeft:%d\n", buffer, image_info->ccdLeft) ; */
1894  return 0;
1895 }
1896 
1897 int ISRequestImageData(int compression, int buffer, int x_offset, int y_offset, int length, int lines)
1898 {
1899  int res;
1900  int i, k;
1901  int img_size;
1902  char errmsg[1024];
1903  int image[320][320];
1904  IMAGE_INFO image_info;
1905 
1906  for (i = 0; i < 320; i++)
1907  {
1908  for (k = 0; k < 320; k++)
1909  {
1910  image[i][k] = -1;
1911  }
1912  }
1913 
1914  res = STV_RequestImage(compression, buffer, x_offset, y_offset, &length, &lines, image, &image_info);
1915 
1916  if (res == 0)
1917  {
1918  STVImg->width = length;
1919  STVImg->height = lines;
1920 
1921  img_size = STVImg->width * STVImg->height * sizeof(unsigned short);
1922 
1923  STVImg->img = malloc(img_size);
1924 
1925  for (i = 0; i < STVImg->height; i++)
1926  { /* x */
1927  for (k = 0; k < STVImg->width; k++)
1928  { /* y */
1929 
1930  STVImg->img[STVImg->width * i + k] = (unsigned short)image[i][k];
1931  /* Uncomment this line in case of doubts about decompressed values and compare */
1932  /* both sets. */
1933  /*fprintf( stderr, "Line: %d %d %d %d\n", i, k, image[i][k], STVImg->img[ STVImg->width* i + k]) ; */
1934 
1935  if (STVImg->img[STVImg->width * i + k] < image_info.minValue)
1936  {
1937  image_info.minValue = STVImg->img[STVImg->width * i + k];
1938  }
1939  if (STVImg->img[STVImg->width * i + k] > image_info.maxValue)
1940  {
1941  image_info.maxValue = STVImg->img[STVImg->width * i + k];
1942  }
1943  }
1944  }
1945  writeFITS("FITS.fits", &image_info, errmsg);
1946  /*fprintf( stderr, "Fits writing message: %s\n", errmsg) ; */
1947  free(STVImg->img);
1948  }
1949  return res;
1950 }
1951 
1952 void ISUpdateDisplay(int buffer, int line)
1953 {
1954  if (!((line + 1) % 10))
1955  {
1956  sprintf(DisplayCT[0].text, "Buffer %2d line: %3d", buffer + 1, line + 1);
1957  strcpy(DisplayBT[0].text, DisplayCT[0].text);
1958  strcpy(DisplayDT[0].text, DisplayCT[0].text);
1959 
1960  DisplayCTP.s = IPS_OK;
1961  IDSetText(&DisplayCTP, NULL);
1962  DisplayBTP.s = IPS_OK;
1963  IDSetText(&DisplayBTP, NULL);
1964  DisplayDTP.s = IPS_OK;
1965  IDSetText(&DisplayDTP, NULL);
1966  }
1967  else if ((line + 1) == 1)
1968  { /* first time */
1969 
1970  IDMessage(mydev, "Image download started");
1971  }
1972  else if (line < 0)
1973  { /* last line */
1974 
1975  line = -line;
1976 
1977  sprintf(DisplayCT[0].text, "Buffer %2d line: %3d", buffer + 1, line + 1);
1978  strcpy(DisplayBT[0].text, DisplayCT[0].text);
1979  strcpy(DisplayDT[0].text, DisplayCT[0].text);
1980 
1981  DisplayCTP.s = IPS_OK;
1982  IDSetText(&DisplayCTP, NULL);
1983  DisplayBTP.s = IPS_OK;
1984  IDSetText(&DisplayBTP, NULL);
1985  DisplayDTP.s = IPS_OK;
1986  IDSetText(&DisplayDTP, NULL);
1987  IDMessage(mydev, "Image download ended, buffer %2d line: %3d", buffer + 1, line);
1988  }
1989 }
hid_device * device
void IERmCallback(int callbackid)
Remove a callback function.
Definition: eventloop.c:577
int IEAddCallback(int readfiledes, IE_CBF *fp, void *p)
Register a new callback, fp, to be called with userpointer as argument when readfiledes is ready.
Definition: eventloop.c:572
void() IE_CBF(int readfiledes, void *userpointer)
Signature of a callback.
Definition: eventloop.c:568
Public interface to INDI's eventloop mechanism.
void ISInit(void)
Definition: fli_wheel.c:121
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ ISS_ON
Definition: indiapi.h:152
#define NARRAY(a)
Handy macro to find the number of elements in array a[]. Must be used with actual array,...
Definition: indiapi.h:500
@ IP_RW
Definition: indiapi.h:186
@ IP_RO
Definition: indiapi.h:184
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
@ ISR_1OFMANY
Definition: indiapi.h:173
int tty_disconnect(int fd)
Closes a tty connection and flushes the bus.
Definition: indicom.c:1148
void IDLog(const char *fmt,...)
Definition: indicom.c:316
Implementations for common driver routines.
INumber * IUFindNumber(const INumberVectorProperty *nvp, const char *name)
Find an INumber member in a number text property.
Definition: indidevapi.c:66
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indidevapi.c:148
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition: indidevapi.c:36
IText * IUFindText(const ITextVectorProperty *tvp, const char *name)
Find an IText member in a vector text property.
Definition: indidevapi.c:56
ISwitch * IUFindSwitch(const ISwitchVectorProperty *svp, const char *name)
Find an ISwitch member in a vector switch property.
Definition: indidevapi.c:76
Interface to the reference INDI C API device implementation on the Device Driver side.
#define INDI_UNUSED(x)
Definition: indidevapi.h:131
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:1308
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1231
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
Definition: indidriver.c:1396
void IDMessage(const char *dev, const char *fmt,...)
Definition: indidriver.c:960
void IDDefNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1104
void IDSetBLOB(const IBLOBVectorProperty *bvp, const char *fmt,...)
Definition: indidriver.c:1287
void IDDefText(const ITextVectorProperty *tvp, const char *fmt,...)
Definition: indidriver.c:1081
void IDDefBLOB(const IBLOBVectorProperty *bvp, const char *fmt,...)
Definition: indidriver.c:1171
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
Definition: indidriver.c:1191
void IDDefSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1127
ISwitchVectorProperty PowerSP
Definition: intelliscope.c:46
const char * OFF
const char * ON
ITextVectorProperty PortTP
Definition: magellan1.cpp:65
std::vector< uint8_t > buffer
One Blob (Binary Large Object) descriptor.
double ccdTemp
Definition: stvdriver.h:128
unsigned int minutes
Definition: stvdriver.h:126
unsigned int year
Definition: stvdriver.h:121
double maxValue
Definition: stvdriver.h:145
unsigned int hours
Definition: stvdriver.h:127
unsigned int width
Definition: stvdriver.h:112
double minValue
Definition: stvdriver.h:144
unsigned int seconds
Definition: stvdriver.h:125
double exposure
Definition: stvdriver.h:114
unsigned int height
Definition: stvdriver.h:112
double pixelSize
Definition: stvdriver.h:143
unsigned int day
Definition: stvdriver.h:123
unsigned int binning
Definition: stvdriver.h:139
unsigned int month
Definition: stvdriver.h:122
One number descriptor.
One switch descriptor.
One text descriptor.
BLOB (Binary Large Object) vector property descriptor.
Definition: indiapi.h:471
Number vector property descriptor.
Definition: indiapi.h:319
char name[MAXINDINAME]
Definition: indiapi.h:323
Switch vector property descriptor.
Definition: indiapi.h:367
char name[MAXINDINAME]
Definition: indiapi.h:371
Text vector property descriptor.
Definition: indiapi.h:246
char name[MAXINDINAME]
Definition: indiapi.h:250
Definition: stv.c:90
int expose
Definition: stv.c:94
unsigned short * img
Definition: stv.c:95
int width
Definition: stv.c:91
int height
Definition: stv.c:92
int frameType
Definition: stv.c:93
int STV_ReceivePacket(unsigned char *buf, int mode)
Definition: stvdriver.c:825
int STV_Interrupt(void)
Definition: stvdriver.c:141
#define currentLines
Definition: stv.c:67
#define CONNECTION_GROUP
Definition: stv.c:59
STVFrames
Definition: stv.c:79
@ DARK_FRAME
Definition: stv.c:82
@ LIGHT_FRAME
Definition: stv.c:80
@ FLAT_FRAME
Definition: stv.c:83
@ BIAS_FRAME
Definition: stv.c:81
int writeFITS(const char *filename, IMAGE_INFO *image_info, char errmsg[])
Definition: stv.c:1558
#define BUTTONS_GROUP
Definition: stv.c:61
int STV_BufferStatus(int buffer)
Definition: stvdriver.c:756
#define currentY
Definition: stv.c:66
void ISCallBack(void)
Definition: stv.c:462
int ISMessageImageInfo(int buffer, IMAGE_INFO *image_info)
Definition: stv.c:1859
int ISRestoreTXDisplay(void)
Definition: stv.c:1833
char tracking_buf[1024]
Definition: stv.c:109
void ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
Update data of an existing blob vector property.
Definition: stv.c:1541
#define currentX
Definition: stv.c:65
#define currentLength
Definition: stv.c:68
int STV_Connect(char *device, int baud)
Definition: stvdriver.c:1482
int init_serial(char *device_name, int bit_rate, int word_size, int parity, int stop_bits)
Definition: stvdriver.c:1526
void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Update the value of an existing switch vector property.
Definition: stv.c:686
int STV_Calibrate(void)
Definition: stvdriver.c:165
void uploadFile(const char *filename)
Definition: stv.c:1710
int STV_Monitor(void)
Definition: stvdriver.c:159
void ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Update the value of an existing text vector property.
Definition: stv.c:1406
int STV_RequestImage(int compression, int buffer, int x_offset, int y_offset, int *length, int *lines, int image[][320], IMAGE_INFO *image_info)
Definition: stvdriver.c:430
int STV_Download(void)
Definition: stvdriver.c:739
int fd
Definition: stv.c:107
int STV_TXDisplay(void)
Definition: stvdriver.c:708
int STV_FileOps(void)
Definition: stvdriver.c:183
int STV_SetDateTime(char *times)
Definition: stvdriver.c:1288
#define currentBuffer
Definition: stv.c:64
void ISGetProperties(const char *dev)
Get Device Properties.
Definition: stv.c:641
int ISTerminateTXDisplay(void)
Definition: stv.c:1789
int STV_Focus(void)
Definition: stvdriver.c:147
int STV_Track(void)
Definition: stvdriver.c:171
void handleError(ISwitchVectorProperty *svp, int err, const char *msg)
int STV_AKey(void)
Definition: stvdriver.c:123
int STV_Image(void)
Definition: stvdriver.c:153
int STV_PrintBuffer(unsigned char *cmdbuf, int n)
Definition: stvdriver.c:1041
int STV_LRRotaryIncrease(void)
Definition: stvdriver.c:105
#define mydev
Definition: stv.c:58
int ISRequestImageData(int compression, int buffer, int x_offset, int y_offset, int length, int lines)
Definition: stv.c:1897
int STV_Setup(void)
Definition: stvdriver.c:135
unsigned int STV_GetBits(unsigned int x, int p, int n)
Definition: stvdriver.c:1190
void ISSnoopDevice(XMLEle *root)
Function defined by Drivers that is called when another Driver it is snooping (by having previously c...
Definition: stv.c:1553
int STV_LRRotaryDecrease(void)
Definition: stvdriver.c:99
void ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Definition: stv.c:1464
void addFITSKeywords(fitsfile *fptr, IMAGE_INFO *image_info)
Definition: stv.c:1597
int STV_RequestImageInfo(int imagebuffer, IMAGE_INFO *image_info)
Definition: stvdriver.c:189
#define SETTINGS_GROUP
Definition: stv.c:60
int STV_TerminateTXDisplay(void)
Definition: stvdriver.c:714
double STV_SetCCDTemperature(double set_value)
Definition: stvdriver.c:1230
#define TEMPFILE_LEN
Definition: stv.c:85
#define IMAGE_GROUP
Definition: stv.c:62
int STV_RequestAck(void)
Definition: stvdriver.c:749
void ISUpdateDisplay(int buffer, int line)
Definition: stv.c:1952
void ISResetButtons(char *message)
Definition: stv.c:415
int STV_UDRotaryDecrease(void)
Definition: stvdriver.c:111
int STV_Display(void)
Definition: stvdriver.c:177
int STV_BKey(void)
Definition: stvdriver.c:129
ITextVectorProperty UTCTP
Definition: stv.c:222
int STV_UDRotaryIncrease(void)
Definition: stvdriver.c:117
#define REQUEST_BUFFER_STATUS
Definition: stvdriver.h:32
#define REQUEST_DOWNLOAD
Definition: stvdriver.h:29
#define REQUEST_DOWNLOAD_ALL
Definition: stvdriver.h:30
#define ACK
Definition: stvdriver.h:35
#define NACK
Definition: stvdriver.h:41
#define DISPLAY_ECHO
Definition: stvdriver.h:38