Instrument Neutral Distributed Interface INDI 2.2.5
stv.c
Go to the documentation of this file.
1#if 0
2 STV Driver
3 Copyright (C) 2006 Markus Wildi, [email protected]
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
72static int compression = OFF;
73static int acquiring = OFF;
74static int guiding = OFF;
75static int processing = OFF;
76
77/* Fits (fli_ccd project) */
85#define TEMPFILE_LEN 16
86
87/* Image (fli_ccd project)*/
88
89typedef struct
90{
91 int width;
92 int height;
94 int expose;
95 unsigned short *img;
96} img_t;
97
98static img_t *STVImg;
99
100/* Function adapted from fli_ccd project */
101
102void addFITSKeywords(fitsfile *fptr, IMAGE_INFO *image_info);
103int writeFITS(const char *filename, IMAGE_INFO *image_info, char errmsg[]);
104void uploadFile(const char *filename);
105
106/* File descriptor and call back id */
107int fd;
108static int cb = -1;
109char tracking_buf[1024];
110
111/* Function prototypes */
112int ISTerminateTXDisplay(void);
113int ISRestoreTXDisplay(void);
114int ISMessageImageInfo(int buffer, IMAGE_INFO *image_info);
115int ISRequestImageData(int compression, int buffer, int x_offset, int y_offset, int length, int lines);
116
117int STV_LRRotaryDecrease(void);
118int STV_LRRotaryIncrease(void);
119int STV_UDRotaryDecrease(void);
120int STV_UDRotaryIncrease(void);
121
122int STV_AKey(void);
123int STV_BKey(void);
124int STV_Setup(void);
125int STV_Interrupt(void);
126int STV_Focus(void);
127int STV_Image(void);
128int STV_Monitor(void);
129int STV_Calibrate(void);
130int STV_Track(void);
131int STV_Display(void);
132int STV_FileOps(void);
133int STV_RequestImageInfo(int imagebuffer, IMAGE_INFO *image_info);
134int STV_BufferStatus(int buffer);
135int STV_RequestImage(int compression, int buffer, int x_offset, int y_offset, int *length, int *lines, int image[][320],
136 IMAGE_INFO *image_info);
137int STV_Download(void);
138int STV_TXDisplay(void);
139int STV_TerminateTXDisplay(void);
140int STV_RequestAck(void);
141unsigned int STV_GetBits(unsigned int x, int p, int n);
142int STV_PrintBuffer(unsigned char *cmdbuf, int n);
143void handleError(ISwitchVectorProperty *svp, int err, const char *msg);
144static void ISInit();
145void ISCallBack(void);
146
147int init_serial(char *device_name, int bit_rate, int word_size, int parity, int stop_bits);
148int STV_ReceivePacket(unsigned char *buf, int mode);
149int STV_Connect(char *device, int baud);
150int STV_SetDateTime(char *times);
151double STV_SetCCDTemperature(double set_value);
152
153static IText StatusT[] = {
154 { "STATUS", "This driver", "is experimental, contact [email protected]", 0, 0, 0 },
155};
156
157static 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
163static ISwitch PowerS[] = {
164 { "CONNECT", "Connect", ISS_OFF, 0, 0 },
165 { "DISCONNECT", "Disconnect", ISS_OFF, 0, 0 },
166};
167
168static ISwitchVectorProperty PowerSP = { mydev, "CONNECTION", "Connection", CONNECTION_GROUP, IP_RW, ISR_1OFMANY,
169 0, IPS_IDLE, PowerS, NARRAY(PowerS), "", 0 };
170
171/* Serial Port */
172
173static IText PortT[] = { { "PORT", "Port", NULL, 0, 0, 0 }, { "SPEED", "Speed", NULL, 0, 0, 0 } };
174
176 mydev, "DEVICE_PORT", "Port", CONNECTION_GROUP, IP_RW, ISR_1OFMANY, IPS_IDLE, PortT, NARRAY(PortT), "", 0
177};
178
179static ISwitch TXDisplayS[] = {
180
181 { "1", "On", ISS_ON, 0, 0 },
182 { "2", "Off", ISS_OFF, 0, 0 },
183};
184
185static ISwitchVectorProperty TXDisplaySP = {
186 mydev, "Update Display", "Update Display", CONNECTION_GROUP, IP_RW, ISR_1OFMANY,
187 0, IPS_IDLE, TXDisplayS, NARRAY(TXDisplayS), "", 0
188};
189
190static IText DisplayCT[] = {
191
192 { "DISPLAYC1", "Line 1", NULL, 0, 0, 0 },
193 { "DISPLAYC2", "Line 2", NULL, 0, 0, 0 }
194};
195
196static ITextVectorProperty DisplayCTP = {
197 mydev, "DISPLAYC", "Display", CONNECTION_GROUP, IP_RO, ISR_1OFMANY, IPS_IDLE, DisplayCT, NARRAY(DisplayCT), "", 0
198};
199
200static IText DisplayBT[] = {
201
202 { "DISPLAYB1", "Line 1", NULL, 0, 0, 0 },
203 { "DISPLAYB2", "Line 2", NULL, 0, 0, 0 }
204};
205
206static ITextVectorProperty DisplayBTP = {
207 mydev, "DISPLAYB", "Display", BUTTONS_GROUP, IP_RO, ISR_1OFMANY, IPS_IDLE, DisplayBT, NARRAY(DisplayBT), "", 0
208};
209
210static IText DisplayDT[] = {
211
212 { "DISPLAYD1", "Line 1", NULL, 0, 0, 0 },
213 { "DISPLAYD2", "Line 2", NULL, 0, 0, 0 }
214};
215
216static ITextVectorProperty DisplayDTP = { mydev, "DISPLAYD", "Display", IMAGE_GROUP, IP_RO, ISR_1OFMANY,
217 IPS_IDLE, DisplayDT, NARRAY(DisplayDT), "", 0 };
218
219/* Setings */
220
221static IText UTCT[] = { { "UTC", "UTC", NULL, 0, 0, 0 } };
222ITextVectorProperty UTCTP = { mydev, "TIME_UTC", "UTC Time", SETTINGS_GROUP, IP_RW, 0, IPS_IDLE, UTCT,
223 NARRAY(UTCT), "", 0 };
224
225static INumber SetCCDTemperatureN[] = {
226 { "TEMPERATURE", "Cel. -55.1, +25.2", "%6.1f", -55.8, 25.2, 0., 16., 0, 0, 0 },
227
228};
229
230static INumberVectorProperty SetCCDTemperatureNP = { mydev,
231 "CCD_TEMPERATURE",
232 "CCD Temperature",
234 IP_RW,
236 IPS_IDLE,
237 SetCCDTemperatureN,
238 NARRAY(SetCCDTemperatureN),
239 "",
240 0 };
241
242/* Buttons */
243static 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
251static ISwitchVectorProperty ControlSP = { mydev, "ParaButtons", "Control", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
252 0, IPS_IDLE, ControlS, NARRAY(ControlS), "", 0 };
253
254static 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
261static ISwitchVectorProperty ValueSP = { mydev, "ValueButtons", "Control", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
262 0, IPS_IDLE, ValueS, NARRAY(ValueS), "", 0 };
263
264static ISwitch AuxiliaryS[] = {
265
266 { "1", "Setup", ISS_OFF, 0, 0 },
267 { "2", "Interrupt", ISS_OFF, 0, 0 },
268
269};
270
271static ISwitchVectorProperty AuxiliarySP = { mydev, "Auxilliary", "", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
272 0, IPS_IDLE, AuxiliaryS, NARRAY(AuxiliaryS), "", 0 };
273
274static 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
281static ISwitchVectorProperty AcquireSP = { mydev, "Acquire", "", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
282 0, IPS_IDLE, AcquireS, NARRAY(AcquireS), "", 0 };
283
284static ISwitch GuideS[] = {
285
286 { "1", "Calibrate", ISS_OFF, 0, 0 },
287 { "2", "Track", ISS_OFF, 0, 0 },
288};
289
290static ISwitchVectorProperty GuideSP = { mydev, "Guide", "", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
291 0, IPS_IDLE, GuideS, NARRAY(GuideS), "", 0 };
292
293static ISwitch ProcessS[] = {
294
295 { "1", "Display/Crosshairs", ISS_OFF, 0, 0 },
296 { "2", "File Ops", ISS_OFF, 0, 0 },
297};
298
299static ISwitchVectorProperty ProcessSP = { mydev, "Process", "", BUTTONS_GROUP, IP_RW, ISR_1OFMANY,
300 0, IPS_IDLE, ProcessS, NARRAY(ProcessS), "", 0 };
301
302static ISwitch CompressionS[] = {
303
304 { "1", "On", ISS_OFF, 0, 0 },
305 { "2", "Off", ISS_OFF, 0, 0 },
306};
307
308static ISwitchVectorProperty CompressionSP = { mydev, "Compression", "", IMAGE_GROUP,
310 CompressionS, NARRAY(CompressionS), "", 0 };
311
312static ISwitch BufferStatusS[] = {
313
314 { "1", "Status", ISS_OFF, 0, 0 },
315};
316
317static ISwitchVectorProperty BufferStatusSP = { mydev, "Buffers", "", IMAGE_GROUP, IP_RW,
318 ISR_1OFMANY, 0, IPS_IDLE, BufferStatusS, NARRAY(BufferStatusS),
319 "", 0 };
320
321static INumber BufferN[] = {
322 { "A0", "Number 1 - 32", "%6.0f", 1., 32., 0., 32., 0, 0, 0 },
323};
324
325static INumberVectorProperty BufferNP = { mydev, "BUFFER_Number", "Buffer", IMAGE_GROUP, IP_RW, ISR_1OFMANY,
326 IPS_IDLE, BufferN, NARRAY(BufferN), "", 0 };
327
328static 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
336static INumberVectorProperty WindowingNP = { mydev, "CCD_FRAME", "Windowing", IMAGE_GROUP, IP_RW, ISR_1OFMANY,
337 IPS_IDLE, WindowingN, NARRAY(WindowingN), "", 0 };
338
339static ISwitch ImageInfoS[] = {
340
341 { "1", "One Image", ISS_OFF, 0, 0 },
342 { "2", "All Images", ISS_OFF, 0, 0 },
343};
344
345static ISwitchVectorProperty ImageInfoSP = { mydev, "Information", "", IMAGE_GROUP, IP_RW, ISR_1OFMANY,
346 0, IPS_IDLE, ImageInfoS, NARRAY(ImageInfoS), "", 0 };
347
348static ISwitch DownloadS[] = {
349
350 { "1", "One Image", ISS_OFF, 0, 0 },
351 { "2", "All Images", ISS_OFF, 0, 0 },
352};
353
354static 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
359static IBLOB imageB = { "CCD1", "Image", "", 0, 0, 0, 0, 0, 0, 0 };
360
361static IBLOBVectorProperty imageBP = { mydev, "Image", "Image", IMAGE_GROUP, IP_RO, 0, IPS_IDLE, &imageB, 1, "", 0 };
362
363/* Initlization routine */
364
365static 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
415void 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 */
641void 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 */
686void 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 {
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
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
1406void 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 */
1464void 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 {
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
1541void 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
1558int 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
1597void 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
1710void 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
1859int 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
1897int 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
1952void 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:581
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:576
void() IE_CBF(int readfiledes, void *userpointer)
Signature of a callback.
Definition eventloop.c:572
Public interface to INDI's eventloop mechanism.
void ISInit(void)
Definition fli_wheel.c:121
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
#define NARRAY(a)
Handy macro to find the number of elements in array a[]. Must be used with actual array,...
Definition indiapi.h:498
@ IP_RW
Definition indiapi.h:184
@ IP_RO
Definition indiapi.h:182
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
@ ISR_1OFMANY
Definition indiapi.h:171
int tty_disconnect(int fd)
Closes a tty connection and flushes the bus.
Definition indicom.c:1224
void IDLog(const char *fmt,...)
Definition indicom.c:305
Implementations for common driver routines.
IText * IUFindText(const ITextVectorProperty *tvp, const char *name)
Find an IText member in a vector text property.
Definition indidevapi.c:265
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition indidevapi.c:366
INumber * IUFindNumber(const INumberVectorProperty *nvp, const char *name)
Find an INumber member in a number text property.
Definition indidevapi.c:275
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition indidevapi.c:44
ISwitch * IUFindSwitch(const ISwitchVectorProperty *svp, const char *name)
Find an ISwitch member in a vector switch property.
Definition indidevapi.c:285
Interface to the reference INDI C API device implementation on the Device Driver side.
#define INDI_UNUSED(x)
Definition indidevapi.h:132
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
void IDMessage(const char *dev, const char *fmt,...)
Definition indidriver.c:983
void IDDefNumber(const INumberVectorProperty *nvp, const char *fmt,...)
void IDSetBLOB(const IBLOBVectorProperty *bvp, const char *fmt,...)
void IDDefText(const ITextVectorProperty *tvp, const char *fmt,...)
void IDDefBLOB(const IBLOBVectorProperty *bvp, const char *fmt,...)
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
void IDDefSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
ISwitchVectorProperty PowerSP
ITextVectorProperty PortTP
Definition magellan1.cpp:65
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:469
Number vector property descriptor.
Definition indiapi.h:317
char name[MAXINDINAME]
Definition indiapi.h:321
Switch vector property descriptor.
Definition indiapi.h:365
char name[MAXINDINAME]
Definition indiapi.h:369
Text vector property descriptor.
Definition indiapi.h:244
char name[MAXINDINAME]
Definition indiapi.h:248
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 OFF
Definition stvdriver.h:26
#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
#define ON
Definition stvdriver.h:27