#include <stdio.h>
#include <stdlib.h>
#include <sys\timeb.h>
#include <time.h>
#include <conio.h>

   /* The following sample code can be compiled with 'JMI' defined,  to   */
   /* create a scope driver program that works with JMI,  Lumicon,  Micro */
   /* Guider,  and assorted other systems using that particular encoder.  */
   /* If it's compiled with SETTING_CIRCLES defined,  you get a "setting  */
   /* circle" driver,  that expects a human to push the telescope to a    */
   /* desired position.                                                   */

#ifdef JMI
#include "ibmcom.h"

int get_jmi_position( double *x, double *y, char *ibuff)
{
   int i, rx;
   long t = time( NULL);

   while( com_rx( ) >= 0 && t + 2L > time( NULL))
      ;                        /* clear any garbage from the buffer */
   com_tx( 'Q');
   for( i = 0; i < 13 && t + 2L > time( NULL); )
      if( (rx = com_rx( )) >= 0)
         if( rx != 13)                 /* ignore the spurious CR sent */
            ibuff[i++] = (char)rx;
   ibuff[i] = '\0';
   *x = atof( ibuff + 1);
   *y = atof( ibuff + 8);
   if( ibuff[0] == '-')
      *x = -*x;
   if( ibuff[7] == '-')
      *y = -*y;
   return( 0);
}
#endif

void main( int argc, char **argv)
{
   int i, slewing = 0, keep_going = 0, j;
   int serial_port = -1;
   double x, y;
   FILE *ofile;
#ifdef JMI
   char tbuff[30];

   printf( "JMI/Lumicon/MicroGuider driver\nCommand line arguments:\n");
#else
   printf( "Setting circle 'driver'...\nCommand line arguments:\n");
#endif
   for( i = 0; i < argc; i++)
      {
      printf( "(%d) %s\n", i, argv[i]);
      if( argv[i][0] == '-')
         {
         if( argv[i][1] == 'k')
            keep_going = 1;
         if( argv[i][1] == 's')
            slewing = 1;
         }
      }

   if( slewing)
      {
      char tbuff[100];
      FILE *ifile = fopen( "slew.dat", "rb");
      double coeffs[20], t0 = 0.;

      printf( "\nContents of SLEW.DAT:\n");
      i = 0;
      while( fgets( tbuff, sizeof( tbuff), ifile))
         {
         double *coeff_ptr = NULL;

         printf( "%s", tbuff);
         if( *tbuff == 's')
            serial_port = atoi( tbuff + 1);
         if( *tbuff == 't')                  /* get the time... */
            t0 = atof( tbuff + 1);
         if( *tbuff == 'x')                  /* read in x, y, alt, az */
            coeff_ptr = coeffs;              /* cubic coeffs...       */
         if( *tbuff == 'y')
            coeff_ptr = coeffs + 4;
         if( *tbuff == 'q')
            coeff_ptr = coeffs + 8;
         if( *tbuff == 'p')
            coeff_ptr = coeffs + 12;
         if( *tbuff == 'r')
            coeff_ptr = coeffs + 16;
         if( coeff_ptr)
            sscanf( tbuff + 1, "%lf %lf %lf %lf",
                  coeff_ptr, coeff_ptr + 1, coeff_ptr + 2, coeff_ptr + 3);
         i++;
         }
      fclose( ifile);

#ifdef JMI
      if( i = com_install( serial_port, 512))
         {
         printf( "com_install() error: %d\n", i);
         exit( 0);
         }
      com_raise_dtr( );
      com_set_speed( 9600);
      com_set_parity( COM_NONE, 1);
#endif
                           /* Here,  we loop and print out the values of   */
                           /* the encoder positions x, y and alt/az values */
                           /* and show them until a key is hit...          */
      printf( "Hit any key when done\n");
      while( !kbhit( ))
         {
         struct _timeb timebuffer;
         double dt, oval[5];

                           /* The _ftime function is,  regrettably,  not     */
                           /* ANSI C or any "standard",  but it does provide */
                           /* 1/18 second precision,  and stepper motors     */
                           /* will need that.                                */
         _ftime( &timebuffer);
         dt = (double)timebuffer.time +(double)timebuffer.millitm / 1000. - t0;
                           /* evaluate all four cubics and show 'em.  In  */
                           /* general,  the alt/az values will be of no   */
                           /* real use.  I suppose they might serve as    */
                           /* warnings:  HEY!  YOUR ALTITUDE  IS ABOUT TO */
                           /* BE NEGATIVE!  STOP TRACKING!  The real data */
                           /* is in the device coordinates x and y.       */
         for( i = 0; i < 5; i++)
            {
            oval[i] = 0.;
            for( j = 3; j >= 0; j--)
               oval[i] = oval[i] * dt + coeffs[i * 4 + j];
            }
                          /* If we had encoders,  we'd show x(computed)      */
                          /* minus x(read from encoders),  and similarly     */
                          /* for y.  With steppers,  we'd use the difference */
                          /* to decide how much movement is required,  and   */
                          /* push the scope in that direction.               */
#ifdef JMI
         get_jmi_position( &x, &y, tbuff);
         printf( "|%s|  ", tbuff);
         oval[0] -= x;
         oval[1] -= y;
#endif
         printf( "x %.2lf  y %.2lf  alt %.4lf  az %.4lf  rotation %.4lf   \r",
               oval[0], oval[1], oval[2], oval[3], oval[4]);
         }
      getch( );
      }

#ifdef SETTING_CIRCLES
                           /* For any other system,  the following request   */
                           /* would be redundant;  we'd either read the      */
                           /* encoders or we'd know where the steppers were. */
                           /* Setting circle users have to actually tell     */
                           /* Guide where the slew ended up.  Guide can then */
                           /* convert the device positions to alt/az.        */
   printf( "\n\nEnter the current setting circle position: ");
   scanf( "%lf %lf", &x, &y);
#endif
#ifdef JMI
   get_jmi_position( &x, &y, tbuff);
   com_deinstall( );
#endif

                           /* Now we give Guide the data and get out...      */
   ofile = fopen( "slew_out.dat", "wb");
   fprintf( ofile, "%lf %lf", x, y);
   fclose( ofile);

   exit( 0);
}
