Instrument Neutral Distributed Interface INDI  2.0.2
stvdriver.c
Go to the documentation of this file.
1 #if 0
2  STV Low Level Driver
3  Copyright (C) 2006 Markus Wildi, markus.wildi@datacomm.ch
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 
48 extern int fd;
49 extern char tracking_buf[];
50 struct termios orig_tty_setting; /* old serial port setting to restore on close */
51 struct 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) ; */
58 void ISUpdateDisplay(int buffer, int line);
59 
60 int STV_portWrite(char *buf, int nbytes);
61 int STV_TXDisplay(void);
62 int STV_TerminateTXDisplay(void);
63 int STV_FileStatus(int);
64 int STV_DownloadComplete(void);
65 int STV_RequestImage(int compression, int buffer, int x_offset, int y_offset, int *length, int *lines, int image[][320],
66  IMAGE_INFO *image_info);
67 int STV_RequestImageData(int compression, int *data, int j, int length, int *values);
68 int STV_Download(void);
69 int STV_DownloadAll(void);
70 int STV_RequestAck(void);
71 int STV_CheckHeaderSum(unsigned char *buf);
72 int STV_CheckDataSum(unsigned char *data);
73 int STV_PrintBuffer(unsigned char *buf, int n);
74 int STV_PrintBufferAsText(unsigned char *buf, int n);
75 int STV_CheckAck(unsigned char *buf);
76 int STV_SendPacket(int cmd, int *data, int n);
77 int STV_ReceivePacket(unsigned char *buf, int mode);
78 int STV_DecompressData(unsigned char *data, int *values, int length, int expected_n_values);
79 int STV_BufferStatus(int buffer);
80 void STV_PrintBits(unsigned int x, int n);
81 
82 unsigned int STV_RecombineInt(unsigned char low_byte, unsigned char high_byte);
83 unsigned int STV_GetBits(unsigned int x, int p, int n);
84 
85 int STV_MenueSetup(int delay);
86 int STV_MenueDateTime(int delay);
87 int STV_MenueCCDTemperature(int delay);
88 
89 typedef struct
90 {
92 
93 } DISPLAY_INFO;
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 
123 int STV_AKey(void)
124 { /* Parameter button */
125  int data[] = { A_KEY_PATTERN };
126  return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
127 }
128 
129 int STV_BKey(void)
130 { /* Value Button */
131  int data[] = { B_KEY_PATTERN };
132  return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
133 }
134 
135 int STV_Setup(void)
136 {
137  int data[] = { SETUP_KEY_PATTERN };
138  return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
139 }
140 
141 int STV_Interrupt(void)
142 {
143  int data[] = { INT_KEY_PATTERN };
144  return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
145 }
146 
147 int STV_Focus(void)
148 {
149  int data[] = { FOCUS_KEY_PATTERN };
150  return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
151 }
152 
153 int STV_Image(void)
154 {
155  int data[] = { IMAGE_KEY_PATTERN };
156  return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
157 }
158 
159 int STV_Monitor(void)
160 {
161  int data[] = { MONITOR_KEY_PATTERN };
162  return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
163 }
164 
165 int STV_Calibrate(void)
166 {
167  int data[] = { CAL_KEY_PATTERN };
168  return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
169 }
170 
171 int STV_Track(void)
172 {
173  int data[] = { TRACK_KEY_PATTERN };
174  return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
175 }
176 
177 int STV_Display(void)
178 {
179  int data[] = { DISPLAY_KEY_PATTERN };
180  return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
181 }
182 
183 int STV_FileOps(void)
184 {
185  int data[] = { FILEOPS_KEY_PATTERN };
186  return STV_SendPacket(SEND_KEY_PATTERN, data, 1);
187 }
188 
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 
430 int 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  }
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 
520 int 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 }
625 int 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 
708 int STV_TXDisplay(void)
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 
728 int 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 
739 int STV_Download(void)
740 {
741  return STV_SendPacket(REQUEST_DOWNLOAD, NULL, 0);
742 }
743 
745 {
746  return STV_SendPacket(REQUEST_DOWNLOAD_ALL, NULL, 0);
747 }
748 
749 int STV_RequestAck(void)
750 {
751  int data[] = { 0x06, 0x06, 0x06 };
752  /* SBIG manual says contains data, which? */
753  return STV_SendPacket(REQUEST_ACK, data, 3);
754 }
755 
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 
775 AGAIN:
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 */
825 int 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 
991 int 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 
1010 int 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 
1041 int 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 }
1060 int 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 
1080 int 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 
1142 int 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 
1169 int 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 
1185 unsigned 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 
1190 unsigned 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 
1196 void 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 
1230 double 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 
1241  STV_MenueCCDTemperature(delay);
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 
1288 int 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 
1445 int 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 
1465 int 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 
1482 int 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  *****************************************************************************/
1526 int 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.
const char * ON
std::vector< uint8_t > buffer
__u8 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
Definition: intelliscope.c:43
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 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