Instrument Neutral Distributed Interface INDI 2.2.5
stvdriver.c
Go to the documentation of this file.
1#if 0
2 STV Low Level Driver
3 Copyright (C) 2006 Markus Wildi, [email protected]
4 The initial work is based on the program STVremote by Shashikiran Ganesh.
5 email: gshashikiran_AT_linuxmail_dot_org
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
21#endif
22
23#define _GNU_SOURCE 1
24
25#include <unistd.h>
26#include <cstring>
27#include <sys/stat.h>
28#include <fcntl.h>
29#include <cerrno>
30#include <stdio.h>
31#include <ctime>
32#include <stdlib.h>
33
34#include "config.h"
35
36#include "stvdriver.h"
37
38#include <libnova/libnova.h>
39
40#ifndef _WIN32
41#include <termios.h>
42#endif
43
44/* INDI Common Routines/RS232 */
45
46#include "indicom.h"
47
48extern int fd;
49extern char tracking_buf[];
50struct termios orig_tty_setting; /* old serial port setting to restore on close */
51struct termios tty_setting; /* new serial port setting */
52
53#define FALSE 0
54#define TRUE 1
55
56/*int tty_read( int fd, char *buf, int nbytes, int timeout, int *nbytes_read) ; */
57/*int tty_write( int fd, const char *buffer, int *nbytes_written) ; */
58void ISUpdateDisplay(int buffer, int line);
59
60int STV_portWrite(char *buf, int nbytes);
61int STV_TXDisplay(void);
63int STV_FileStatus(int);
64int STV_DownloadComplete(void);
65int STV_RequestImage(int compression, int buffer, int x_offset, int y_offset, int *length, int *lines, int image[][320],
66 IMAGE_INFO *image_info);
67int STV_RequestImageData(int compression, int *data, int j, int length, int *values);
68int STV_Download(void);
69int STV_DownloadAll(void);
70int STV_RequestAck(void);
71int STV_CheckHeaderSum(unsigned char *buf);
72int STV_CheckDataSum(unsigned char *data);
73int STV_PrintBuffer(unsigned char *buf, int n);
74int STV_PrintBufferAsText(unsigned char *buf, int n);
75int STV_CheckAck(unsigned char *buf);
76int STV_SendPacket(int cmd, int *data, int n);
77int STV_ReceivePacket(unsigned char *buf, int mode);
78int STV_DecompressData(unsigned char *data, int *values, int length, int expected_n_values);
79int STV_BufferStatus(int buffer);
80void STV_PrintBits(unsigned int x, int n);
81
82unsigned int STV_RecombineInt(unsigned char low_byte, unsigned char high_byte);
83unsigned int STV_GetBits(unsigned int x, int p, int n);
84
85int STV_MenueSetup(int delay);
86int STV_MenueDateTime(int delay);
87int STV_MenueCCDTemperature(int delay);
88
89typedef struct
90{
92
94
96
97/* STV Buttons */
98
100{
101 int data[] = { LR_ROTARY_DECREASE_PATTERN };
102 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
103}
104
106{
107 int data[] = { LR_ROTARY_INCREASE_PATTERN };
108 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
109}
110
112{
113 int data[] = { UD_ROTARY_DECREASE_PATTERN };
114 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
115}
116
118{
119 int data[] = { UD_ROTARY_INCREASE_PATTERN };
120 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
121}
122
123int STV_AKey(void)
124{ /* Parameter button */
125 int data[] = { A_KEY_PATTERN };
126 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
127}
128
129int STV_BKey(void)
130{ /* Value Button */
131 int data[] = { B_KEY_PATTERN };
132 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
133}
134
135int STV_Setup(void)
136{
137 int data[] = { SETUP_KEY_PATTERN };
138 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
139}
140
142{
143 int data[] = { INT_KEY_PATTERN };
144 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
145}
146
147int STV_Focus(void)
148{
149 int data[] = { FOCUS_KEY_PATTERN };
150 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
151}
152
153int STV_Image(void)
154{
155 int data[] = { IMAGE_KEY_PATTERN };
156 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
157}
158
159int STV_Monitor(void)
160{
161 int data[] = { MONITOR_KEY_PATTERN };
162 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
163}
164
166{
167 int data[] = { CAL_KEY_PATTERN };
168 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
169}
170
171int STV_Track(void)
172{
173 int data[] = { TRACK_KEY_PATTERN };
174 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
175}
176
177int STV_Display(void)
178{
179 int data[] = { DISPLAY_KEY_PATTERN };
180 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
181}
182
183int STV_FileOps(void)
184{
185 int data[] = { FILEOPS_KEY_PATTERN };
186 return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
187}
188
189int STV_RequestImageInfo(int buffer, IMAGE_INFO *image_info)
190{
191 int i;
192 int length;
193 int res;
194 int data[] = { buffer };
195 unsigned char buf[1024];
196 unsigned int value[21];
197
198 if ((res = STV_BufferStatus(buffer)) != 0)
199 {
200 if (res == 1)
201 {
202 /*fprintf( stderr," STV_RequestImageInfo buffer empty %d\n", buffer) ; */
203 return res; /* Buffer is empty */
204 }
205 else
206 {
207 fprintf(stderr, " STV_RequestImageInfo error %d\n", res);
208 return res;
209 }
210 }
211
212 res = STV_SendPacket(REQUEST_IMAGE_INFO, data, 1);
213 usleep(50000);
214 res = STV_ReceivePacket(buf, 0);
215
216 if (buf[1] != REQUEST_IMAGE_INFO)
217 {
218 /*length= buf[3] * 0x100 + buf[2] ; */
219 /*res= STV_PrintBuffer(buf, 6+ length+ 2) ; */
220
221 AGAINI:
222 if ((res = STV_ReceivePacket(buf, 0)) < 0)
223 { /* STV answers with a packet 0x03 sometimes, should be 0x04 */
224 return -1;
225 ;
226 }
227 if (buf[1] != REQUEST_IMAGE_INFO)
228 { /* Second try */
229 fprintf(stderr, "STV_RequestImageInfo: expected REQUEST_IMAGE_INFO, received %d, try again\n", buf[1]);
230 goto AGAINI;
231 }
232 }
233
234 length = buf[3] * 0x100 + buf[2];
235
236 /* DECODE it */
237
238 for (i = 6; i < length; i += 2)
239 {
240 value[(i - 6) / 2] = STV_RecombineInt(buf[i], buf[i + 1]);
241 }
242
243 image_info->descriptor = value[0];
244
245 /* Decode the descriptor */
246
247 /*STV_PrintBits(( unsigned int)value[0], 16) ; */
248
249 if ((image_info->descriptor & ID_BITS_MASK) == ID_BITS_10)
250 {
251 /* fprintf( stderr, "ADC Resolution: 10 bits\n") ; */
252 }
253 else if ((image_info->descriptor & ID_BITS_MASK) == ID_BITS_8)
254 {
255 /*fprintf( stderr, "Resolution: 8 bits (focus mode only)\n") ; */
256 }
257
258 if ((image_info->descriptor & ID_UNITS_MASK) == ID_UNITS_INCHES)
259 {
260 /*fprintf( stderr, "Units: inch\n") ; */
261 }
262 else if ((image_info->descriptor & ID_UNITS_MASK) == ID_UNITS_CM)
263 {
264 /*fprintf( stderr, "Unis: cm\n") ; */
265 }
266
267 if ((image_info->descriptor & ID_SCOPE_MASK) == ID_SCOPE_REFRACTOR)
268 {
269 /*fprintf( stderr, "Refractor\n") ; */
270 }
271 else if ((image_info->descriptor & ID_SCOPE_MASK) == ID_SCOPE_REFLECTOR)
272 {
273 /*fprintf( stderr, "Reflector\n") ; */
274 }
275
276 if ((image_info->descriptor & ID_DATETIME_MASK) == ID_DATETIME_VALID)
277 {
278 /*fprintf( stderr, "Date and time valid\n") ; */
279 }
280 else if ((image_info->descriptor & ID_DATETIME_MASK) == ID_DATETIME_INVALID)
281 {
282 /*fprintf( stderr, "Date and time invalid\n") ; */
283 }
284
285 if ((image_info->descriptor & ID_BIN_MASK) == ID_BIN_1X1)
286 {
287 image_info->binning = 1;
288 }
289 else if ((image_info->descriptor & ID_BIN_MASK) == ID_BIN_2X2)
290 {
291 image_info->binning = 2;
292 }
293 else if ((image_info->descriptor & ID_BIN_MASK) == ID_BIN_3X3)
294 {
295 image_info->binning = 3;
296 }
297
298 if ((image_info->descriptor & ID_PM_MASK) == ID_PM_PM)
299 {
300 /*fprintf( stderr, "Time: PM\n") ; */
301 }
302 else if ((image_info->descriptor & ID_PM_MASK) == ID_PM_AM)
303 {
304 /*fprintf( stderr, "Time: AM\n") ; */
305 }
306
307 /* ToDo: Include that to the fits header */
308 if ((image_info->descriptor & ID_FILTER_MASK) == ID_FILTER_LUNAR)
309 {
310 /*fprintf( stderr, "Filter: Lunar\n") ; */
311 }
312 else if ((image_info->descriptor & ID_FILTER_MASK) == ID_FILTER_NP)
313 {
314 /*fprintf( stderr, "Filter: clear\n") ; */
315 }
316
317 /* ToDo: Include that to the fits header */
318 if ((image_info->descriptor & ID_DARKSUB_MASK) == ID_DARKSUB_YES)
319 {
320 /*fprintf( stderr, "Drak sub yes\n") ; */
321 }
322 else if ((image_info->descriptor & ID_DARKSUB_MASK) == ID_DARKSUB_NO)
323 {
324 /*fprintf( stderr, "Dark sub no\n") ; */
325 }
326
327 if ((image_info->descriptor & ID_MOSAIC_MASK) == ID_MOSAIC_NONE)
328 {
329 /*fprintf( stderr, "Is NOT a mosaic\n") ; */
330 }
331 else if ((image_info->descriptor & ID_MOSAIC_MASK) == ID_MOSAIC_SMALL)
332 {
333 /*fprintf( stderr, "Is a small mosaic\n") ; */
334 }
335 else if ((image_info->descriptor & ID_MOSAIC_MASK) == ID_MOSAIC_LARGE)
336 {
337 /*fprintf( stderr, "Is a large mosaic\n") ; */
338 }
339
340 image_info->height = value[1];
341 image_info->width = value[2];
342 image_info->top = value[3];
343 image_info->left = value[4];
344
345 /* Exposure time */
346
347 if ((value[5] >= 100) && (value[5] <= 60000))
348 {
349 image_info->exposure = ((float)value[5]) * 0.01;
350 }
351 else if ((value[5] >= 60001) && (value[5] <= 60999))
352 {
353 image_info->exposure = ((float)value[5] - 60000.) * .001;
354 }
355 else
356 {
357 fprintf(stderr, "Error Exposure time %d\n", value[5]);
358 image_info->exposure = -1.;
359 }
360
361 image_info->noExposure = value[6];
362 image_info->analogGain = value[7];
363 image_info->digitalGain = value[8];
364 image_info->focalLength = value[9];
365 image_info->aperture = value[10];
366
367 image_info->packedDate = value[11];
368 image_info->year = STV_GetBits(value[11], 6, 7) + 1999;
369 image_info->day = STV_GetBits(value[11], 11, 5);
370 image_info->month = STV_GetBits(value[11], 15, 4);
371
372 image_info->packedTime = value[12];
373 image_info->seconds = STV_GetBits(value[12], 5, 6);
374 image_info->minutes = STV_GetBits(value[12], 11, 6);
375 image_info->hours = STV_GetBits(value[12], 15, 4);
376
377 if ((image_info->descriptor & ID_PM_PM) > 0)
378 {
379 image_info->hours += 12;
380 }
381
382 if ((value[13] & 0x8000) == 0x8000)
383 {
384 image_info->ccdTemp = (float)(0xffff - value[13]) / 100.;
385 }
386 else
387 {
388 image_info->ccdTemp = (float)value[13] / 100.;
389 }
390
391 image_info->siteID = value[14];
392 image_info->eGain = value[15];
393 image_info->background = value[16];
394 image_info->range = value[17];
395 image_info->pedestal = value[18];
396 image_info->ccdTop = value[19];
397 image_info->ccdLeft = value[20];
398
399 /* fprintf( stderr, "descriptor:%d 0x%2x 0x%2x\n", image_info->descriptor, buf[6], buf[6+1]) ; */
400 /* fprintf( stderr, "height:%d\n", image_info->height) ; */
401 /* fprintf( stderr, "width:%d\n", image_info->width) ; */
402 /* fprintf( stderr, "top:%d\n", image_info->top) ; */
403 /* fprintf( stderr, "left:%d\n", image_info->left) ; */
404 /* fprintf( stderr, "exposure:%f\n", image_info->exposure) ; */
405 /* fprintf( stderr, "noExposure:%d\n", image_info->noExposure) ; */
406 /* fprintf( stderr, "analogGain:%d\n", image_info->analogGain) ; */
407 /* fprintf( stderr, "digitalGain:%d\n", image_info->digitalGain) ; */
408 /* fprintf( stderr, "focalLength:%d\n", image_info->focalLength) ; */
409 /* fprintf( stderr, "aperture:%d\n", image_info->aperture) ; */
410 /* fprintf( stderr, "packedDate:%d\n", image_info->packedDate) ; */
411 /* fprintf( stderr, "Year:%d\n", image_info->year) ; */
412 /* fprintf( stderr, "Day:%d\n", image_info->day) ; */
413 /* fprintf( stderr, "Month:%d\n", image_info->month) ; */
414 /* fprintf( stderr, "packedTime:%d\n", image_info->packedTime) ; */
415 /* fprintf( stderr, "Seconds:%d\n", image_info->seconds) ; */
416 /* fprintf( stderr, "minutes:%d\n", image_info->minutes) ; */
417 /* fprintf( stderr, "hours:%d\n", image_info->hours) ; */
418 /* fprintf( stderr, "ccdTemp:%f\n", image_info->ccdTemp) ; */
419 /* fprintf( stderr, "siteID:%d\n", image_info->siteID) ; */
420 /* fprintf( stderr, "eGain:%d\n", image_info->eGain) ; */
421 /* fprintf( stderr, "background:%d\n", image_info->background) ; */
422 /* fprintf( stderr, "range :%d\n", image_info->range ) ; */
423 /* fprintf( stderr, "pedestal:%d\n", image_info->pedestal) ; */
424 /* fprintf( stderr, "ccdTop :%d\n", image_info->ccdTop) ; */
425 /* fprintf( stderr, "ccdLeft:%d\n", image_info->ccdLeft) ; */
426
427 return 0;
428}
429
430int STV_RequestImage(int compression, int buffer, int x_offset, int y_offset, int *length, int *lines, int image[][320],
431 IMAGE_INFO *image_info)
432{
433 int i, j;
434 int res;
435 int n_values;
436 unsigned char buf[0xffff];
437 int values[1024];
438 int data[] = { 0, y_offset, *length, buffer }; /* Offset row, Offset line, length, buffer number */
439 int XOFF;
440
441 /* fprintf(stderr, "STV_RequestImage: --------------------------------buffer= %d, %d\n", buffer, lines) ; */
442
443 if ((res = STV_RequestImageInfo(buffer, image_info)) != 0)
444 { /* Trigger for download */
445 /* buffer empty */
446 return res;
447 }
448 res = STV_BKey(); /* "press" the STV Value button */
449 usleep(50000);
450 res = STV_ReceivePacket(buf, 0);
451
452 /* Check the boundaries obtained from the image data versus windowing */
453 /* Take the smaller boundaries in each direction */
454
455 if (x_offset > image_info->height)
456 {
457 x_offset = image_info->height;
458 }
459 XOFF = image_info->top + x_offset;
460
461 if (y_offset > image_info->width)
462 {
463 y_offset = image_info->width;
464 }
465 data[1] = image_info->left + y_offset;
466
467 if (*length > image_info->width - y_offset)
468 {
469 *length = image_info->width - y_offset;
470 }
471 data[2] = *length;
472
473 if (*lines > image_info->height - x_offset)
474 {
475 *lines = image_info->height - x_offset;
476 }
477
478 /*fprintf(stderr, "STV_RequestImage: DATA 0=%d, 1=%d, 2=%d, 3=%d, length=%d, lines=%d\n", data[0], data[1], data[2], data[3], *length, *lines) ; */
479
480 for (j = 0; j < *lines; j++)
481 {
482 data[0] = j + XOFF; /*line */
483
484 if ((n_values = STV_RequestImageData(compression, data, j, *length, values)) < 0)
485 {
486 fprintf(stderr, "STV_RequestImage: Calling STV_RequestImageData failed %d\n", n_values);
487 return n_values;
488 }
489 else
490 {
491 for (i = 0; i < n_values; i++)
492 {
493 image[j][i] = values[i];
494 }
495 ISUpdateDisplay(buffer, j);
496 }
497 }
498 /* Read the 201th line, see mosaic mode */
499
500 /* ToDo: analyze/display the data or use them in the fits header(s) */
501 data[0] = 200; /*line */
502
503 if ((res = STV_RequestImageData(1, data, 200, *length, values)) < 0)
504 {
505 return res;
506 }
507 else
508 {
509 for (i = 0; i < n_values; i++)
510 {
511 /* fprintf( stderr, "%d: %d ", i, values[i]) ; */
512 }
513 /* fprintf( stderr, "\n") ; */
514 }
515 res = STV_DownloadComplete();
516 ISUpdateDisplay(buffer, -j);
517 return 0;
518}
519
520int STV_RequestImageData(int compression, int *data, int j, int length, int *values)
521{
522 int i;
523 int res;
524 int data_length;
525 int n_values;
526 unsigned char buf[0xffff];
527
528 data_length = -1;
529
530 if (compression == ON)
531 { /* compressed download */
532
533 if ((res = STV_SendPacket(REQUEST_COMPRESSED_IMAGE_DATA, data, 4)) != 0)
534 {
535 fprintf(stderr, "STV_RequestImageData: could not write\n");
536 return -1;
537 }
538
539 AGAINC:
540 if ((res = STV_ReceivePacket(buf, 0)) > 0)
541 {
542 if (buf[1] != REQUEST_COMPRESSED_IMAGE_DATA)
543 {
544 if (buf[1] != DISPLAY_ECHO)
545 {
546 if (buf[1] != ACK)
547 {
548 fprintf(stderr, "STV_RequestImageData: expected REQUEST_COMPRESSED_IMAGE_DATA, received %2x\n",
549 buf[1]);
550 }
551 }
552 goto AGAINC;
553 }
554
555 data_length = (int)buf[3] * 0x100 + (int)buf[2];
556
557 if ((n_values = STV_DecompressData((buf + 6), values, data_length, length)) < 0)
558 {
559 n_values = -n_values;
560 fprintf(stderr, "SEVERE ERROR on Line %d, pixel position=%d\n", j, n_values);
561 _exit(-1);
562 }
563
564 if (n_values == length)
565 {
566 return n_values;
567 }
568 else
569 {
570 fprintf(stderr, "SEVERE Error: Length not equal, Line: %d, %d != %d, data %2x %2x, values %d, %d\n", j,
571 n_values, length, buf[6 + length - 2], buf[6 + length - 1], values[n_values - 2],
572 values[n_values - 1]);
573 _exit(1);
574 }
575 }
576 else
577 {
578 fprintf(stderr, "Error: waiting for data on the serial port at line %d\n", j);
579 return -1;
580 }
581 }
582 else
583 { /* uncompressed download */
584
585 if ((res = STV_SendPacket(REQUEST_IMAGE_DATA, data, 4)) == 0)
586 {
587 AGAINU:
588 if ((res = STV_ReceivePacket(buf, 0)) > 0)
589 {
590 if (buf[1] != REQUEST_IMAGE_DATA)
591 {
592 if (buf[1] != DISPLAY_ECHO)
593 {
594 if (buf[1] != ACK)
595 {
596 fprintf(stderr, "STV_RequestImageData: expected REQUEST_IMAGE_DATA, received %2x\n",
597 buf[1]);
598 }
599 }
600 goto AGAINU;
601 }
602
603 data_length = (int)buf[3] * 0x100 + (int)buf[2];
604
605 for (i = 0; i < data_length; i += 2)
606 {
607 values[i / 2] = STV_RecombineInt(buf[6 + i], buf[7 + i]);
608 }
609 return data_length / 2;
610 /*ISUpdateDisplay( buffer, j) ; */ /* Update the display of the INDI client */
611 }
612 else
613 {
614 fprintf(stderr, "Error: waiting for data on the serial port at line %d\n", j);
615 return -1;
616 }
617 }
618 else
619 {
620 fprintf(stderr, "STV_RequestImageData: error writing %d\n", res);
621 }
622 }
623 return 0;
624}
625int STV_DecompressData(unsigned char *data, int *values, int length, int expected_n_values)
626{
627 int i, n_values;
628 int value;
629 int base;
630
631 base = STV_RecombineInt(data[0], data[1]); /*STV Manual says: MSB then LSB! */
632
633 values[0] = base;
634 i = 2;
635 n_values = 1;
636
637 while (i < length)
638 {
639 if (((data[i] & 0xc0)) == 0x80)
640 { /*two bytes, first byte: bit 7 set, 6 cleared, 14 bits data */
641
642 if ((data[i] & 0x20) == 0x20)
643 { /* minus sign set? */
644
645 value =
646 -((int)(((~data[i] & 0x1f)) * 0x100) + (((int)(~data[i + 1])) & 0xff)) - 1; /* value without sign */
647 }
648 else
649 {
650 value = (int)((data[i] & 0x1f) * 0x100) + (int)(data[i + 1]);
651 }
652
653 base = value + base; /* new base value */
654 values[n_values++] = base; /*pixel data */
655 i += 2;
656 }
657 else if (((data[i] & 0x80)) == 0)
658 { /* one byte: bit 7 clear (7 bits data) */
659
660 if ((data[i] & 0x40) == 0x40)
661 { /* minus sign set? */
662
663 value = -(int)((~(data[i])) & 0x3f) - 1; /* value without sign */
664 }
665 else
666 {
667 value = (int)(data[i] & 0x3f);
668 /*fprintf( stderr, "Value 7P: %d, pixel value: %d, length %d, pix=%d\n", value, value+ base, length, n_values) ; */
669 }
670 /* Sometimes the STV send a 0 at the end, thats not very likely a pixel to pixel variation */
671 /* I checked the last decompressed pixel value against the last uncompressed pixel value */
672 /* with different images - it seems to be ok. */
673 if ((value == 0) && (n_values == expected_n_values))
674 {
675 /*fprintf( stderr, "Ignoring byte %d, Zero difference obtained values: %d\n", i, n_values) ; */
676 }
677 else
678 {
679 base = value + base;
680 values[n_values++] = base;
681 }
682 i++;
683 }
684 else if (((data[i] & 0xc0)) == 0xc0)
685 { /*two bytes, values= pixel_n/4 */
686
687 /*STV_PrintBits( data[ i], 8) ; */
688 /*STV_PrintBits( data[ i+ 1], 8) ; */
689
690 value = 4 * ((int)((data[i] & 0x3f) * 0x100) + (int)(data[i + 1]));
691 /*fprintf( stderr, "Value 14P: %d, pixel value: %d, length %d, pix=%d\n", value, value+ base, length, n_values) ; */
692
693 base = value;
694 values[n_values++] = value;
695
696 i += 2;
697 /*return -n_values ; */
698 }
699 else
700 {
701 fprintf(stderr, "Unknown compression case: %2x, length %d, i=%d\n", data[i], length, i);
702 return -n_values; /* exit */
703 }
704 }
705 return n_values;
706}
707
709{
710 int data[] = { TRUE };
711 return STV_SendPacket(DISPLAY_ECHO, data, 1);
712}
713
715{
716 int res;
717 int data[] = { FALSE };
718
719 res = STV_SendPacket(DISPLAY_ECHO, data, 1);
720
721 /* Despite the manual says so, I not always see an ACK packet */
722 /* So i flush it for the moment */
723
724 tcflush(fd, TCIOFLUSH);
725 return res;
726}
727
728int STV_FileStatus(int status)
729{
730 int data[] = { status };
731 return STV_SendPacket(FILE_STATUS, data, 1);
732}
733
735{
736 return STV_SendPacket(DOWNLOAD_COMPLETE, NULL, 0);
737}
738
740{
741 return STV_SendPacket(REQUEST_DOWNLOAD, NULL, 0);
742}
743
745{
746 return STV_SendPacket(REQUEST_DOWNLOAD_ALL, NULL, 0);
747}
748
750{
751 int data[] = { 0x06, 0x06, 0x06 };
752 /* SBIG manual says contains data, which? */
753 return STV_SendPacket(REQUEST_ACK, data, 3);
754}
755
756int STV_BufferStatus(int buffer)
757{
758 unsigned char buf[1024];
759 int buffers;
760 int res;
761 int val;
762
763 /*fprintf(stderr, "STV_BufferStatus entering\n") ; */
764 usleep(50000);
765 if ((res = STV_SendPacket(REQUEST_BUFFER_STATUS, NULL, 0)) < 0)
766 {
767 fprintf(stderr, "STV_BufferStatus: Error requesting buffer status: %d\n", buffer);
768 return -1;
769 }
770 else
771 {
772 /*fprintf( stderr, "STV_BufferStatus %2d\n", buffer) ; */
773 }
774
775AGAIN:
776 if ((res = STV_ReceivePacket(buf, 0)) < 0)
777 {
778 fprintf(stderr, "STV_BufferStatus: Error reading: %d\n", res);
779 return -1;
780 ;
781 }
782
783 if (buf[1] == REQUEST_BUFFER_STATUS)
784 {
785 buffers = STV_RecombineInt(buf[6], buf[7]) * 0x10000 + STV_RecombineInt(buf[8], buf[9]);
786
787 if ((val = STV_GetBits(buffers, buffer, 1)) == 1)
788 {
789 res = 0; /* image present */
790 }
791 else
792 {
793 /*fprintf( stderr, "STV_BufferStatus %2d is empty\n", buffer) ; */
794 res = 1; /* empty */
795 }
796 }
797 else
798 {
799 /* The SBIG manual does not specify an ACK, but it is there (at least sometimes) */
800 if ((val = STV_CheckAck(buf)) == 0)
801 {
802 /*fprintf( stderr, "STV_BufferStatus SAW ACK, reading again\n") ; */
803 goto AGAIN;
804 }
805 /* The SBIG manual does not specify the cmd in the answer */
806 if (buf[1] != DISPLAY_ECHO)
807 {
808 fprintf(stderr, "STV_BufferStatus: unexpected cmd byte received %d\n", buf[1]);
809 val = STV_RecombineInt(buf[2], buf[3]);
810 res = STV_PrintBuffer(buf, 6 + val + 2);
811 return -1;
812 }
813 else
814 {
815 /* a display packet is silently ignored, there are many of this kind */
816 fprintf(stderr, "STV_BufferStatus DISPLAY_ECHO received, try again\n");
817 return -1;
818 }
819 }
820 /* fprintf(stderr, "STV_BufferStatus leaving\n") ; */
821 return res;
822}
823/* Low level communication */
824/* STV_ReceivePacket n_bytes read */
825int STV_ReceivePacket(unsigned char *buf, int mode)
826{
827 int i, j, k;
828 int n_bytes = 0;
829 int length = 0;
830 int res;
831 int trb = 0;
832 int pos = 0;
833 char display1[25];
834 char display2[25];
835
836 j = 0;
837 tracking_buf[0] = 0;
838
839 /*fprintf( stderr,"R") ; */
840
841 while (pos < 6)
842 {
843 /* Read the header first, calculate length of data */
844 /* At higher speeds the data arrives in smaller chunks, assembling the packet */
845 if ((trb = read(fd, (char *)(buf + pos), 1)) == -1)
846 {
847 fprintf(stderr, "Error, %s\n", strerror(errno));
848 }
849
850 if (buf[0] == 0xa5)
851 {
852 if (pos == 5)
853 {
854 pos++;
855 break;
856 }
857 else
858 {
859 pos += trb; /* could be zero */
860 }
861 }
862 else
863 {
864 /* In tracking mode the STV sends raw data (time, brightnes, centroid x,y). */
865 /* Under normal operation here appear pieces of a packet. This could happen */
866 /* on start up or if something goes wrong. */
867
868 tracking_buf[j++] = buf[pos];
869 /*fprintf(stderr, "READ: %d, read %d, pos %d, 0x%2x< %c\n", j, trb, pos, buf[pos], buf[pos]) ; */
870 }
871 }
872
873 if (j > 0)
874 {
875 /* Sometimes the packets are corrupt, e.g. at the very beginning */
876 /* Or it is tracking information */
877
878 tracking_buf[j] = 0;
879
880 if (mode == ON)
881 { /* Tracking mode */
882
883 fprintf(stderr, "%s\n", tracking_buf);
884 }
885 else
886 {
887 for (k = 0; k < j; k++)
888 {
889 if (!(tracking_buf[k] > 29 && tracking_buf[k] < 127))
890 {
891 tracking_buf[k] = 0x20; /* simply */
892 }
893 }
894 fprintf(stderr, "Not a packet: length: %d >%s<\n", j, tracking_buf);
895 }
896 }
897
898 n_bytes = pos;
899
900 if ((buf[0] == 0xa5) && (pos == 6))
901 { /* Check the sanity of the header part */
902 if ((res = STV_CheckHeaderSum(buf)) == 0)
903 {
904 length = (int)buf[3] * 0x100 + (int)buf[2];
905 ;
906
907 if (length > 0)
908 {
909 trb = 0;
910 while (pos < 6 + length + 2)
911 { /* header, data, check sum */
912
913 /* At higher speeds the data arrives in smaller chunks, assembling the packet */
914
915 if ((trb = read(fd, (char *)(buf + pos), (6 + length + 2) - pos)) == -1)
916 {
917 fprintf(stderr, "STV_ReceivePacket: Error reading at serial port, %s\n", strerror(errno));
918 return -1;
919 }
920 pos += trb;
921 }
922 n_bytes += pos;
923 /*fprintf(stderr, "STV_ReceivePacket: LEAVING LOOP length %d, to read %d, read %d, pos %d\n", length, (6 + length + 2)- pos, trb, pos) ; */
924 }
925 }
926 else
927 {
928 fprintf(stderr, "STV_ReceivePacket: Header check failed\n");
929 return -1;
930 }
931 }
932 else if (pos > 0)
933 {
934 for (i = 0; i < 6; i++)
935 {
936 if (buf[i] == 0xa5)
937 {
938 fprintf(stderr, "STV_ReceivePacket: pos= %d, saw 0xa5 at %d\n", pos, i);
939 }
940 }
941 return -1;
942 }
943 else
944 {
945 fprintf(stderr, "STV_ReceivePacket: NO 0xa5 until pos= %d\n", pos);
946 return -1;
947 }
948
949 if (length > 0)
950 { /* Check the sanity of the data */
951
952 if ((res = STV_CheckDataSum(buf)) == -1)
953 {
954 return -1;
955 }
956 }
957 /* Analyse the display and retrieve the values */
958 if (buf[1] == DISPLAY_ECHO)
959 {
960 for (i = 0; i < 24; i++)
961 {
962 display1[i] = buf[i + 6];
963 if (display1[i] == 0)
964 {
965 display1[i] = 0x32;
966 }
967 display2[i] = buf[i + 30];
968 if (display2[i] == 0)
969 {
970 display2[i] = 0x32;
971 }
972 }
973 display1[24] = 0;
974 display2[24] = 0;
975
976 /*fprintf(stderr, "STV_ReceivePacket: DISPLAY1 %s<\n", display1) ; */
977 /*fprintf(stderr, "STV_ReceivePacket: DISPLAY2 %s<\n", display2) ; */
978
979 /* CCD temperature */
980 if ((res = strncmp("CCD Temp.", display2, 9)) == 0)
981 {
982 float t;
983 res = sscanf(display2, "CCD Temp. %f", &t);
984 di.ccd_temperature = (double)t;
985 /*fprintf(stderr, "STV_ReceivePacket: Read from DISPLAY2 %g<\n", di.ccd_temperature ) ; */
986 } /* further values can be stored here */
987 }
988 return n_bytes;
989}
990
991int STV_CheckHeaderSum(unsigned char *buf)
992{
993 int sum = buf[0] + buf[1] + buf[2] + buf[3]; /* Calculated header sum */
994 int sumbuf = STV_RecombineInt(buf[4], buf[5]); /* STV packet header sum */
995
996 if (buf[0] != 0xa5)
997 {
998 fprintf(stderr, "STV_CheckHeaderSum: Wrong start byte, skipping\n");
999 return -1;
1000 }
1001
1002 if (sum != sumbuf)
1003 {
1004 fprintf(stderr, "STV_CheckHeaderSum: NOK: %d==%d\n", sum, sumbuf);
1005 return -1;
1006 }
1007 return 0;
1008}
1009
1010int STV_CheckDataSum(unsigned char *buf)
1011{
1012 /* *buf points to the beginning of the packet */
1013
1014 int j, n;
1015 int sum = 0;
1016 int sumbuf = 0;
1017
1018 n = STV_RecombineInt(buf[2], buf[3]);
1019
1020 if (n == 0)
1021 {
1022 fprintf(stderr, "STV_CheckDataSum: No data present\n");
1023 return 0;
1024 }
1025 sumbuf = STV_RecombineInt(buf[6 + n], buf[6 + n + 1]);
1026
1027 for (j = 0; j < n; j++)
1028 {
1029 sum += (int)buf[6 + j];
1030 }
1031 sum = sum & 0xffff;
1032
1033 if (sum != sumbuf)
1034 {
1035 fprintf(stderr, "DATA SUM NOK: %d !=%d\n", sum, sumbuf);
1036 return -1;
1037 }
1038 return 0;
1039}
1040
1041int STV_PrintBuffer(unsigned char *buf, int n)
1042{
1043 /* For debugging purposes only */
1044 int i;
1045
1046 fprintf(stderr, "\nHEADER: %d bytes ", n);
1047 for (i = 0; i < n; i++)
1048 {
1049 if (i == 6)
1050 {
1051 fprintf(stderr, "\nDATA : ");
1052 }
1053 fprintf(stderr, "%d:0x%2x<>%c< >>", i, (unsigned char)buf[i], (unsigned char)buf[i]);
1054 /*STV_PrintBits((unsigned int) buf[i], 8) ; */
1055 }
1056 fprintf(stderr, "\n");
1057
1058 return 0;
1059}
1060int STV_PrintBufferAsText(unsigned char *buf, int n)
1061{
1062 /* For debugging purposes only */
1063 int i;
1064
1065 fprintf(stderr, "\nHEADER: %d bytes ", n);
1066 for (i = 0; i < n; i++)
1067 {
1068 if (i == 6)
1069 {
1070 fprintf(stderr, "\nDATA : ");
1071 }
1072 fprintf(stderr, "%c", (unsigned char)buf[i]);
1073 }
1074 fprintf(stderr, "\n");
1075
1076 return 0;
1077}
1078/* Aggregates a STV command packet */
1079
1080int STV_SendPacket(int cmd, int *data, int n)
1081{
1082 char buf[1024];
1083
1084 int j, l;
1085 int res;
1086 int sum; /* check sum */
1087
1088 /* Header section */
1089 buf[0] = (unsigned char)0xa5; /* start byte */
1090 buf[1] = (unsigned char)cmd; /* command byte */
1091 buf[2] = (unsigned char)2 * n; /* data length N (low byte) */
1092 buf[3] = (unsigned char)0x00; /* data length N (high byte) */
1093
1094 sum = buf[0] + buf[1] + buf[2] + buf[3]; /* header checksum */
1095 buf[4] = (unsigned char)sum % 0x100; /* header checksum low byte */
1096 buf[5] = (unsigned char)(sum / 0x100); /* header checksum high byte */
1097
1098 /* DATA section */
1099 l = 0;
1100 if (n > 0)
1101 {
1102 l = 2; /* Two bytes per value are sent to STV */
1103 for (j = 0; j < 2 * n; j += 2)
1104 {
1105 buf[6 + j] = (unsigned char)(data[j / 2] % 0x100); /* data low byte */
1106 buf[7 + j] = (unsigned char)(data[j / 2] / 0x100); /* data high byte */
1107 }
1108
1109 sum = 0;
1110 for (j = 0; j < 2 * n; j++)
1111 {
1112 if ((int)buf[6 + j] < 0)
1113 {
1114 sum = sum + 0xff + (int)buf[6 + j] + 1;
1115 }
1116 else
1117 {
1118 sum = sum + (int)buf[6 + j];
1119 }
1120 }
1121 buf[6 + 2 * n] = (unsigned char)(sum % 0x10000); /* data checksum (low byte) */
1122 buf[7 + 2 * n] = (unsigned char)(sum / 0x100); /* data checksum (high byte) */
1123 }
1124 if ((res = STV_CheckHeaderSum((unsigned char *)buf)) != 0)
1125 { /* Check outgoing packet as well */
1126
1127 fprintf(stderr, "STV_SendPacket: corrupt header\n");
1128
1129 if (n > 0)
1130 {
1131 if ((res = STV_CheckDataSum((unsigned char *)buf)) != 0)
1132 {
1133 fprintf(stderr, "STV_SendPacket: corrupt data\n");
1134 }
1135 }
1136 }
1137 return STV_portWrite(buf, 8 + l * n);
1138}
1139
1140/* Returns 0 or -1 in case of an error */
1141
1142int STV_portWrite(char *buf, int nbytes)
1143{
1144 int bytesWritten = 0;
1145
1146 /*fprintf( stderr,"w") ; */
1147 while (nbytes > 0)
1148 {
1149 if ((bytesWritten = write(fd, buf, nbytes)) == -1)
1150 {
1151 fprintf(stderr, "STV_portWrite: Error writing at serial port, %s\n", strerror(errno));
1152 /* return -1 ; */
1153 }
1154
1155 if (bytesWritten < 0)
1156 {
1157 fprintf(stderr, "STV_portWrite: Error writing\n");
1158 return -1;
1159 }
1160 else
1161 {
1162 buf += bytesWritten;
1163 nbytes -= bytesWritten;
1164 }
1165 }
1166 return nbytes;
1167}
1168
1169int STV_CheckAck(unsigned char *buf)
1170{
1171 /* Watch out for an ACK, for debugging purposes only */
1172 int i;
1173 unsigned char ackseq[] = { 0xa5, 0x06, 0x00, 0x00, 0xab, 0x00 };
1174
1175 for (i = 0; i < 6; i++)
1176 {
1177 if (buf[i] != ackseq[i])
1178 {
1179 return -1;
1180 }
1181 }
1182 return 0;
1183}
1184
1185unsigned int STV_RecombineInt(unsigned char low_byte, unsigned char high_byte)
1186{
1187 return (unsigned int)high_byte * (unsigned int)0x100 + (unsigned int)low_byte;
1188}
1189
1190unsigned int STV_GetBits(unsigned int x, int p, int n)
1191{ /* from the C book */
1192
1193 return (x >> (p + 1 - n)) & ~(~0 << n);
1194}
1195
1196void STV_PrintBits(unsigned int x, int n)
1197{
1198 /* debugging purposes only */
1199 int i;
1200 int res;
1201 fprintf(stderr, "STV_PrintBits:\n");
1202
1203 if (n > 8)
1204 {
1205 fprintf(stderr, "54321098 76543210\n");
1206 }
1207 else
1208 {
1209 fprintf(stderr, "76543210\n");
1210 }
1211
1212 for (i = n; i > 0; i--)
1213 {
1214 if ((i == 8) && (n > 8))
1215 {
1216 fprintf(stderr, " ");
1217 }
1218 if ((res = STV_GetBits(x, i - 1, 1)) == 0)
1219 {
1220 fprintf(stderr, "0");
1221 }
1222 else
1223 {
1224 fprintf(stderr, "1");
1225 }
1226 }
1227 fprintf(stderr, "\n");
1228}
1229
1230double STV_SetCCDTemperature(double set_value)
1231{
1232 int i;
1233 int res;
1234 int delay = 40000;
1235 unsigned char buf[1024];
1236 /* 1st step */
1237 res = STV_Interrupt(); /* Reset Display */
1238 tcflush(fd, TCIOFLUSH);
1239 usleep(100000);
1240
1242
1243 for (i = 0; i < 100; i++)
1244 { /* Change to the highest temperature */
1245 res = STV_LRRotaryIncrease();
1246 tcflush(fd, TCIOFLUSH);
1247 usleep(delay);
1248 }
1249
1250 di.ccd_temperature = 25.2; /* The actual value is set in STV_ReceivePacket, needed to enter the while() loop */
1251 i = 0;
1252 while (set_value < di.ccd_temperature)
1253 {
1254 /*fprintf( stderr, "STV_SetCCDTemperature %g %g\n", set_value, di.ccd_temperature) ; */
1255 res = STV_LRRotaryDecrease(); /* Lower CCD temperature */
1256 /*fprintf(stderr, ":") ; */
1257 usleep(10000);
1258 res = STV_TerminateTXDisplay();
1259 usleep(10000);
1260 res = STV_TXDisplay(); /* That's the trick, STV sends at least one display */
1261 res = STV_ReceivePacket(buf, 0); /* discard it */
1262
1263 /*STV_PrintBufferAsText( buf, res) ; */
1264 if ((res != 62) || (i++ > 100))
1265 { /* why 56 + 6?, 6 + 48 + 6 */
1266 STV_PrintBuffer(buf, res);
1267 /*STV_PrintBufferAsText( buf, res) ; */
1268 return 0.0;
1269 }
1270 }
1271 res = STV_Interrupt();
1272
1273 return di.ccd_temperature;
1274}
1275
1277{
1278 int res;
1279
1280 res = STV_MenueSetup(delay);
1281 usleep(delay);
1282 res = STV_UDRotaryIncrease(); /* Change to CCD Temperature */
1283 /*usleep( delay) ; */
1284 tcflush(fd, TCIOFLUSH);
1285 return 0;
1286}
1287
1288int STV_SetDateTime(char *times)
1289{
1290 int i;
1291 int res;
1292 int turn;
1293 struct ln_date utm;
1294 int delay = 20000;
1295 /*fprintf(stderr, "STV_SetTime\n") ; */
1296
1297 if ((times == NULL) || ((res = strlen(times)) == 0))
1298 ln_get_date_from_sys(&utm);
1299 else
1300 {
1301 if (extractISOTime(times, &utm) < 0)
1302 {
1303 fprintf(stderr, "Bad time string %s\n", times);
1304 return -1;
1305 }
1306 }
1307 /* Print out the date and time in the standard format. */
1308 /*fprintf( stderr, "TIME %s\n", asctime (utc)) ; */
1309
1310 /* 1st step */
1311 res = STV_Interrupt(); /* Reset Display */
1312 usleep(delay);
1313 tcflush(fd, TCIOFLUSH);
1314
1315 res = STV_MenueDateTime(delay);
1316 usleep(delay);
1317 res = STV_MenueDateTime(delay); /* This not an error */
1318 usleep(delay);
1319
1320 for (i = 0; i < 13; i++)
1321 { /* Reset Month menu to the lef most position */
1322 res = STV_LRRotaryDecrease();
1323 usleep(delay);
1324 }
1325
1326 for (i = 0; i < utm.months; i++)
1327 { /* Set Month menu */
1328 res = STV_LRRotaryIncrease();
1329 usleep(delay);
1330 tcflush(fd, TCIOFLUSH);
1331 }
1332 res = STV_AKey(); /* Press the Parameter button */
1333 usleep(delay);
1334 tcflush(fd, TCIOFLUSH);
1335
1336 for (i = 0; i < 32; i++)
1337 { /* Reset Day menu to the lef most position */
1338 res = STV_LRRotaryDecrease();
1339 usleep(delay);
1340 tcflush(fd, TCIOFLUSH);
1341 }
1342
1343 for (i = 0; i < utm.days - 1; i++)
1344 { /* Set Day menu -1? */
1345 res = STV_LRRotaryIncrease();
1346 usleep(delay);
1347 tcflush(fd, TCIOFLUSH);
1348 }
1349 res = STV_AKey(); /* Press the Parameter button */
1350 usleep(delay);
1351 tcflush(fd, TCIOFLUSH);
1352
1353 for (i = 0; i < 128; i++)
1354 { /* Reset Year menu to the lef most position, ATTENTION */
1355 res = STV_LRRotaryDecrease();
1356
1357 usleep(delay); /* sleep a 1/100 second */
1358 tcflush(fd, TCIOFLUSH);
1359 }
1360
1361 /* JM: Is this how you want not? Please verify the code! */
1362 int ymenu = utm.years % 100;
1363
1364 for (i = 0; i < ymenu; i++)
1365 { /* Set Year menu */
1366 res = STV_LRRotaryIncrease();
1367 usleep(delay);
1368 tcflush(fd, TCIOFLUSH);
1369 }
1370 res = STV_AKey(); /* Press the Parameter button */
1371 usleep(delay);
1372 tcflush(fd, TCIOFLUSH);
1373
1374 for (i = 0; i < 25; i++)
1375 { /* Reset Hour menu to the lef most position, ATTENTION */
1376 res = STV_LRRotaryDecrease();
1377 usleep(delay);
1378 tcflush(fd, TCIOFLUSH);
1379 }
1380 for (i = 0; i < utm.hours; i++)
1381 { /* Set Hour menu */
1382 res = STV_LRRotaryIncrease();
1383 usleep(delay);
1384 tcflush(fd, TCIOFLUSH);
1385 }
1386 res = STV_AKey(); /* Press the Parameter button */
1387 usleep(delay);
1388 tcflush(fd, TCIOFLUSH);
1389
1390 for (i = 0; i < 61; i++)
1391 { /* Reset Minute menu to the lef most position, ATTENTION */
1392 res = STV_LRRotaryDecrease();
1393 usleep(delay);
1394 tcflush(fd, TCIOFLUSH);
1395 }
1396 for (i = 0; i < utm.minutes; i++)
1397 { /* Set Minute menu */
1398 res = STV_LRRotaryIncrease();
1399 usleep(delay);
1400 tcflush(fd, TCIOFLUSH);
1401 }
1402 res = STV_AKey(); /* Press the Parameter button */
1403 tcflush(fd, TCIOFLUSH);
1404 for (i = 0; i < 5; i++)
1405 { /* Reset Seconds menu to the lef most position, ATTENTION */
1406 res = STV_LRRotaryDecrease();
1407 usleep(delay);
1408 tcflush(fd, TCIOFLUSH);
1409 }
1410
1411 if (utm.seconds < 15)
1412 {
1413 turn = 0;
1414 }
1415 else if (utm.seconds < 30)
1416 {
1417 turn = 1;
1418 }
1419 else if (utm.seconds < 45)
1420 {
1421 turn = 2;
1422 }
1423 else
1424 {
1425 turn = 3;
1426 }
1427
1428 for (i = 0; i < turn; i++)
1429 { /* Set Seconds menu, steps of 15 seconds */
1430 res = STV_LRRotaryIncrease();
1431 usleep(delay);
1432 tcflush(fd, TCIOFLUSH);
1433 }
1434 res = STV_AKey(); /* Press the Parameter button */
1435 usleep(delay);
1436 tcflush(fd, TCIOFLUSH);
1437
1438 res = STV_BKey(); /* Press the Parameter button */
1439 usleep(delay);
1440 tcflush(fd, TCIOFLUSH);
1441 res = STV_Interrupt();
1442 return 0;
1443}
1444
1445int STV_MenueDateTime(int delay)
1446{
1447 int i;
1448 int res;
1449
1450 res = STV_MenueSetup(delay);
1451 usleep(delay);
1452 res = STV_BKey(); /* Press the Value button */
1453 usleep(delay);
1454
1455 for (i = 0; i < 8; i++)
1456 { /* Reset Date menu to the lef most position */
1457
1458 res = STV_UDRotaryDecrease();
1459 usleep(delay);
1460 tcflush(fd, TCIOFLUSH);
1461 }
1462 return 0;
1463}
1464
1465int STV_MenueSetup(int delay)
1466{
1467 int i;
1468 int res;
1469
1470 res = STV_Setup(); /* Change to Setup */
1471 usleep(delay);
1472
1473 for (i = 0; i < 16; i++)
1474 { /* Reset Setup menu to the lef most position */
1475 res = STV_UDRotaryDecrease();
1476 usleep(delay);
1477 tcflush(fd, TCIOFLUSH);
1478 }
1479 return 0;
1480}
1481
1482int STV_Connect(char *device, int baud)
1483{
1484 /*fprintf( stderr, "STV_Connect\n") ; */
1485 if ((fd = init_serial(device, baud, 8, 0, 1)) == -1)
1486 {
1487 fprintf(stderr, "Error on port %s, %s\n", device, strerror(errno));
1488 return -1;
1489 }
1490
1491 return fd;
1492}
1493
1494/******************************************************************************
1495 * shutdown_serial(..)
1496 ******************************************************************************
1497 * Restores terminal settings of open serial port device and close the file.
1498 * Arguments:
1499 * fd: file descriptor of open serial port device.
1500 *****************************************************************************/
1502{
1503 if (fd > 0)
1504 {
1505 if (tcsetattr(fd, TCSANOW, &orig_tty_setting) < 0)
1506 {
1507 perror("shutdown_serial: can't restore serial device's terminal settings.");
1508 }
1509 close(fd);
1510 }
1511}
1512/******************************************************************************
1513 * init_serial(..)
1514 ******************************************************************************
1515 * Opens and initializes a serial device and returns it's file descriptor.
1516 * Arguments:
1517 * device_name : device name string of the device to open (/dev/ttyS0, ...)
1518 * bit_rate : bit rate
1519 * word_size : number of data bits, 7 or 8, USE 8 DATA BITS with modbus
1520 * parity : 0=no parity, 1=parity EVEN, 2=parity ODD
1521 * stop_bits : number of stop bits : 1 or 2
1522 * Return:
1523 * file descriptor of successfully opened serial device
1524 * or -1 in case of error.
1525 *****************************************************************************/
1526int init_serial(char *device_name, int bit_rate, int word_size, int parity, int stop_bits)
1527{
1528 int fd;
1529 char *msg;
1530
1531 /* open serial device */
1532 fd = open(device_name, O_RDWR | O_NOCTTY);
1533 if (fd < 0)
1534 {
1535 if (asprintf(&msg, "init_serial: open %s failed", device_name) < 0)
1536 perror(NULL);
1537 else
1538 perror(msg);
1539
1540 return -1;
1541 }
1542
1543 /* save current tty settings */
1544 if (tcgetattr(fd, &orig_tty_setting) < 0)
1545 {
1546 perror("init_serial: can't get terminal parameters.");
1547 return -1;
1548 }
1549
1550 /* Control Modes */
1551 /* Set bps rate */
1552 int bps;
1553 switch (bit_rate)
1554 {
1555 case 0:
1556 bps = B0;
1557 break;
1558 case 50:
1559 bps = B50;
1560 break;
1561 case 75:
1562 bps = B75;
1563 break;
1564 case 110:
1565 bps = B110;
1566 break;
1567 case 134:
1568 bps = B134;
1569 break;
1570 case 150:
1571 bps = B150;
1572 break;
1573 case 200:
1574 bps = B200;
1575 break;
1576 case 300:
1577 bps = B300;
1578 break;
1579 case 600:
1580 bps = B600;
1581 break;
1582 case 1200:
1583 bps = B1200;
1584 break;
1585 case 1800:
1586 bps = B1800;
1587 break;
1588 case 2400:
1589 bps = B2400;
1590 break;
1591 case 4800:
1592 bps = B4800;
1593 break;
1594 case 9600:
1595 bps = B9600;
1596 break;
1597 case 19200:
1598 bps = B19200;
1599 break;
1600 case 38400:
1601 bps = B38400;
1602 break;
1603 case 57600:
1604 bps = B57600;
1605 break;
1606 case 115200:
1607 bps = B115200;
1608 break;
1609 case 230400:
1610 bps = B230400;
1611 break;
1612 default:
1613 if (asprintf(&msg, "init_serial: %d is not a valid bit rate.", bit_rate) < 0)
1614 perror(NULL);
1615 else
1616 perror(msg);
1617 return -1;
1618 }
1619 if ((cfsetispeed(&tty_setting, bps) < 0) || (cfsetospeed(&tty_setting, bps) < 0))
1620 {
1621 perror("init_serial: failed setting bit rate.");
1622 return -1;
1623 }
1624
1625 /* Control Modes */
1626 /* set no flow control word size, parity and stop bits. */
1627 /* Also don't hangup automatically and ignore modem status. */
1628 /* Finally enable receiving characters. */
1629 tty_setting.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | HUPCL | CRTSCTS);
1630 /* #ifdef CBAUDEX */
1631 /*tty_setting.c_cflag &= ~(CBAUDEX); */
1632 /*#endif */
1633 /*#ifdef CBAUDEXT */
1634 /*tty_setting.c_cflag &= ~(CBAUDEXT); */
1635 /*#endif */
1636 tty_setting.c_cflag |= (CLOCAL | CREAD);
1637
1638 /* word size */
1639 switch (word_size)
1640 {
1641 case 5:
1642 tty_setting.c_cflag |= CS5;
1643 break;
1644 case 6:
1645 tty_setting.c_cflag |= CS6;
1646 break;
1647 case 7:
1648 tty_setting.c_cflag |= CS7;
1649 break;
1650 case 8:
1651 tty_setting.c_cflag |= CS8;
1652 break;
1653 default:
1654
1655 fprintf(stderr, "Default\n");
1656 if (asprintf(&msg, "init_serial: %d is not a valid data bit count.", word_size) < 0)
1657 perror(NULL);
1658 else
1659 perror(msg);
1660
1661 return -1;
1662 }
1663
1664 /* parity */
1665 switch (parity)
1666 {
1667 case PARITY_NONE:
1668 break;
1669 case PARITY_EVEN:
1670 tty_setting.c_cflag |= PARENB;
1671 break;
1672 case PARITY_ODD:
1673 tty_setting.c_cflag |= PARENB | PARODD;
1674 break;
1675 default:
1676
1677 fprintf(stderr, "Default1\n");
1678 if (asprintf(&msg, "init_serial: %d is not a valid parity selection value.", parity) < 0)
1679 perror(NULL);
1680 else
1681 perror(msg);
1682
1683 return -1;
1684 }
1685
1686 /* stop_bits */
1687 switch (stop_bits)
1688 {
1689 case 1:
1690 break;
1691 case 2:
1692 tty_setting.c_cflag |= CSTOPB;
1693 break;
1694 default:
1695 fprintf(stderr, "Default2\n");
1696 if (asprintf(&msg, "init_serial: %d is not a valid stop bit count.", stop_bits) < 0)
1697 perror(NULL);
1698 else
1699 perror(msg);
1700
1701 return -1;
1702 }
1703 /* Control Modes complete */
1704
1705 /* Ignore bytes with parity errors and make terminal raw and dumb. */
1706 tty_setting.c_iflag &= ~(PARMRK | ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON | IXANY);
1707 tty_setting.c_iflag |= INPCK | IGNPAR | IGNBRK;
1708
1709 /* Raw output. */
1710 tty_setting.c_oflag &= ~(OPOST | ONLCR);
1711
1712 /* Local Modes */
1713 /* Don't echo characters. Don't generate signals. */
1714 /* Don't process any characters. */
1715 tty_setting.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN | NOFLSH | TOSTOP);
1716 tty_setting.c_lflag |= NOFLSH;
1717
1718 /* blocking read until 1 char arrives */
1719 tty_setting.c_cc[VMIN] = 1;
1720 tty_setting.c_cc[VTIME] = 0;
1721
1722 /* now clear input and output buffers and activate the new terminal settings */
1723 tcflush(fd, TCIOFLUSH);
1724 if (tcsetattr(fd, TCSANOW, &tty_setting))
1725 {
1726 perror("init_serial: failed setting attributes on serial port.");
1728 return -1;
1729 }
1730 return fd;
1731}
#define PARITY_ODD
Definition Lx.cpp:14
#define PARITY_EVEN
Definition Lx.cpp:13
#define PARITY_NONE
Definition Lx.cpp:12
hid_device * device
int errno
Implementations for common driver routines.
int extractISOTime(const char *timestr, struct ln_date *iso_date)
Extract ISO 8601 time and store it in a tm struct.
uint8_t cmd[4]
Definition pwc-ioctl.h:2
double ccd_temperature
Definition stvdriver.c:91
double ccdTemp
Definition stvdriver.h:128
int digitalGain
Definition stvdriver.h:117
unsigned int minutes
Definition stvdriver.h:126
unsigned int ccdLeft
Definition stvdriver.h:134
unsigned int year
Definition stvdriver.h:121
unsigned int hours
Definition stvdriver.h:127
unsigned int top
Definition stvdriver.h:113
unsigned int width
Definition stvdriver.h:112
unsigned int pedestal
Definition stvdriver.h:133
unsigned int packedTime
Definition stvdriver.h:124
unsigned int left
Definition stvdriver.h:113
unsigned int descriptor
Definition stvdriver.h:111
unsigned int noExposure
Definition stvdriver.h:115
unsigned int seconds
Definition stvdriver.h:125
unsigned int eGain
Definition stvdriver.h:130
double exposure
Definition stvdriver.h:114
unsigned int range
Definition stvdriver.h:132
unsigned int height
Definition stvdriver.h:112
unsigned int ccdTop
Definition stvdriver.h:134
unsigned int day
Definition stvdriver.h:123
unsigned int binning
Definition stvdriver.h:139
unsigned int background
Definition stvdriver.h:131
unsigned int siteID
Definition stvdriver.h:129
unsigned int month
Definition stvdriver.h:122
unsigned int packedDate
Definition stvdriver.h:120
unsigned int focalLength
Definition stvdriver.h:118
unsigned int aperture
Definition stvdriver.h:119
unsigned int analogGain
Definition stvdriver.h:116
int STV_ReceivePacket(unsigned char *buf, int mode)
Definition stvdriver.c:825
int STV_Interrupt(void)
Definition stvdriver.c:141
int STV_CheckHeaderSum(unsigned char *buf)
Definition stvdriver.c:991
int STV_PrintBuffer(unsigned char *buf, int n)
Definition stvdriver.c:1041
int STV_BufferStatus(int buffer)
Definition stvdriver.c:756
int STV_FileStatus(int)
Definition stvdriver.c:728
int STV_MenueDateTime(int delay)
Definition stvdriver.c:1445
int STV_DownloadComplete(void)
Definition stvdriver.c:734
int STV_RequestImageInfo(int buffer, IMAGE_INFO *image_info)
Definition stvdriver.c:189
int STV_RequestImageData(int compression, int *data, int j, int length, int *values)
Definition stvdriver.c:520
char tracking_buf[]
Definition stv.c:109
int STV_DecompressData(unsigned char *data, int *values, int length, int expected_n_values)
Definition stvdriver.c:625
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
int STV_Calibrate(void)
Definition stvdriver.c:165
int STV_Monitor(void)
Definition stvdriver.c:159
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
int STV_TXDisplay(void)
Definition stvdriver.c:708
int STV_FileOps(void)
Definition stvdriver.c:183
int STV_CheckAck(unsigned char *buf)
Definition stvdriver.c:1169
int STV_SetDateTime(char *times)
Definition stvdriver.c:1288
int STV_Focus(void)
Definition stvdriver.c:147
int STV_Track(void)
Definition stvdriver.c:171
unsigned int STV_RecombineInt(unsigned char low_byte, unsigned char high_byte)
Definition stvdriver.c:1185
int STV_MenueSetup(int delay)
Definition stvdriver.c:1465
int STV_AKey(void)
Definition stvdriver.c:123
int STV_Image(void)
Definition stvdriver.c:153
struct termios tty_setting
Definition stvdriver.c:51
#define TRUE
Definition stvdriver.c:54
#define FALSE
Definition stvdriver.c:53
int STV_CheckDataSum(unsigned char *data)
Definition stvdriver.c:1010
struct termios orig_tty_setting
Definition stvdriver.c:50
int STV_LRRotaryIncrease(void)
Definition stvdriver.c:105
int STV_PrintBufferAsText(unsigned char *buf, int n)
Definition stvdriver.c:1060
int STV_Setup(void)
Definition stvdriver.c:135
unsigned int STV_GetBits(unsigned int x, int p, int n)
Definition stvdriver.c:1190
int STV_LRRotaryDecrease(void)
Definition stvdriver.c:99
void shutdown_serial(int fd)
Definition stvdriver.c:1501
DISPLAY_INFO di
Definition stvdriver.c:95
int STV_portWrite(char *buf, int nbytes)
Definition stvdriver.c:1142
int STV_TerminateTXDisplay(void)
Definition stvdriver.c:714
int STV_DownloadAll(void)
Definition stvdriver.c:744
double STV_SetCCDTemperature(double set_value)
Definition stvdriver.c:1230
void STV_PrintBits(unsigned int x, int n)
Definition stvdriver.c:1196
int STV_RequestAck(void)
Definition stvdriver.c:749
int STV_MenueCCDTemperature(int delay)
Definition stvdriver.c:1276
void ISUpdateDisplay(int buffer, int line)
Definition stv.c:1952
int STV_UDRotaryDecrease(void)
Definition stvdriver.c:111
int STV_Display(void)
Definition stvdriver.c:177
int STV_BKey(void)
Definition stvdriver.c:129
int STV_UDRotaryIncrease(void)
Definition stvdriver.c:117
int STV_SendPacket(int cmd, int *data, int n)
Definition stvdriver.c:1080
#define ID_BIN_3X3
Definition stvdriver.h:79
#define ID_PM_MASK
Definition stvdriver.h:80
#define ID_FILTER_MASK
Definition stvdriver.h:83
#define REQUEST_ACK
Definition stvdriver.h:40
#define UD_ROTARY_INCREASE_PATTERN
Definition stvdriver.h:47
#define ID_BIN_MASK
Definition stvdriver.h:76
#define B_KEY_PATTERN
Definition stvdriver.h:57
#define ID_FILTER_LUNAR
Definition stvdriver.h:84
#define IMAGE_KEY_PATTERN
Definition stvdriver.h:60
#define ID_MOSAIC_NONE
Definition stvdriver.h:90
#define UD_ROTARY_DECREASE_PATTERN
Definition stvdriver.h:46
#define ID_UNITS_CM
Definition stvdriver.h:69
#define ID_FILTER_NP
Definition stvdriver.h:85
#define REQUEST_BUFFER_STATUS
Definition stvdriver.h:32
#define ID_DARKSUB_YES
Definition stvdriver.h:87
#define SEND_KEY_PATTERN
Definition stvdriver.h:37
#define REQUEST_DOWNLOAD
Definition stvdriver.h:29
#define LR_ROTARY_INCREASE_PATTERN
Definition stvdriver.h:45
#define ID_BITS_MASK
Definition stvdriver.h:64
#define INT_KEY_PATTERN
Definition stvdriver.h:58
#define REQUEST_DOWNLOAD_ALL
Definition stvdriver.h:30
#define ID_DATETIME_MASK
Definition stvdriver.h:73
#define CAL_KEY_PATTERN
Definition stvdriver.h:51
#define ID_UNITS_INCHES
Definition stvdriver.h:68
#define REQUEST_IMAGE_DATA
Definition stvdriver.h:34
#define REQUEST_IMAGE_INFO
Definition stvdriver.h:33
#define LR_ROTARY_DECREASE_PATTERN
Definition stvdriver.h:44
#define ACK
Definition stvdriver.h:35
#define ID_UNITS_MASK
Definition stvdriver.h:67
#define ID_DARKSUB_NO
Definition stvdriver.h:88
#define ID_MOSAIC_SMALL
Definition stvdriver.h:91
#define FOCUS_KEY_PATTERN
Definition stvdriver.h:59
#define ID_BITS_10
Definition stvdriver.h:65
#define DOWNLOAD_COMPLETE
Definition stvdriver.h:31
#define ID_PM_AM
Definition stvdriver.h:82
#define ID_DARKSUB_MASK
Definition stvdriver.h:86
#define REQUEST_COMPRESSED_IMAGE_DATA
Definition stvdriver.h:36
#define MONITOR_KEY_PATTERN
Definition stvdriver.h:61
#define ID_BIN_2X2
Definition stvdriver.h:78
#define ID_BITS_8
Definition stvdriver.h:66
#define DISPLAY_ECHO
Definition stvdriver.h:38
#define TRACK_KEY_PATTERN
Definition stvdriver.h:52
#define FILEOPS_KEY_PATTERN
Definition stvdriver.h:54
#define ID_BIN_1X1
Definition stvdriver.h:77
#define DISPLAY_KEY_PATTERN
Definition stvdriver.h:53
#define SETUP_KEY_PATTERN
Definition stvdriver.h:56
#define ID_PM_PM
Definition stvdriver.h:81
#define ID_DATETIME_INVALID
Definition stvdriver.h:75
#define FILE_STATUS
Definition stvdriver.h:39
#define ON
Definition stvdriver.h:27
#define ID_MOSAIC_LARGE
Definition stvdriver.h:92
#define ID_DATETIME_VALID
Definition stvdriver.h:74
#define ID_SCOPE_REFLECTOR
Definition stvdriver.h:72
#define ID_MOSAIC_MASK
Definition stvdriver.h:89
#define ID_SCOPE_MASK
Definition stvdriver.h:70
#define ID_SCOPE_REFRACTOR
Definition stvdriver.h:71
#define A_KEY_PATTERN
Definition stvdriver.h:55