/* rhspiral.c For Lynxos -- based on masscomp code, in turn from Zeos code */ /* July 8, 1992 */ /* Moves telescope in a spiral pattern */ /* !!!!!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ /* There seems to be a bug in the Lynxos "read" routine. When I call */ /* read( , , 1) to read 1 byte from the terminal, it should */ /* give me one byte per call. Therefore, to read the VT100 cursor key */ /* sequences, which consist of 3 bytes, it should take 3 calls to read. */ /* However, read keeps giving me 3 bytes even though I only request one. */ /* I've added a kludge fix which detects this and parses the three bytes */ /* but I haven't been able to test the "correct POSIX" code. */ /* There is some danger it may not work when the Lynxos "read" call */ /* is fixed. */ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ #define timefactor 1000000.0 /* Use this for Lynxos */ /* Conversion between dwell time */ /* and internal time units. */ #define _POSIX_SOURCE #include #include #include #include #include #include #include #include #include #include #include struct wiro_memory *tracking_info; #include "/usr/local/wiro/tracking/wirotypes.h" #include "/usr/local/wiro/tracking/track.h" #include "/usr/local/wiro/tracking/wiro.h" struct wiro_memory *tinfo, *get_tinfo(); double home_ha, /* Position at start of spiral */ home_dec, paused_ha, /* Position at pause. */ paused_dec, dtime = 0.5, /* Dwell time, in seconds per point */ pitch = 5.0, /* Default pitch, in arcseconds */ degstep; /* Step size, in degrees. */ int size = 1, /* Length of the current side, in steps. */ step = 0, /* Position along current side, in steps. */ for_rev = 1, /* 1 = forward (expanding) -1 = reverse (contracting ) */ dir = 0; /* Forward direction of current size */ /* 0=W, 1=N, 2=E, 3=S */ int moving = 0, /* True if spiral in underway */ good_vals = 0, /* True if parameters are ok. */ quit = 0; /* True if program should exit. */ /* int32 iwait; */ /* Wait time in microseconds. */ int iwait; /* For unknown reasons the typedef doesn't work */ /* Unix variables */ int tty; char command; char commandbuf[129]; /* Needed because of problems with read */ /* "read( , , 1) keeps reading more than 1 */ char tbuf[129]; void spiral( ); /* Main spiral code. */ void turn_left( ); /* Turn a corner going forward */ void turn_right( ); /* Turn a corner going backwards. */ void take_step( ); /* Move one step in direction specified */ void do_command( ); /* Read command from keyboard & execute it. */ void stop( ); /* Halts spiral, records paused position. */ void go( ); /* Start motion if parameters are ok. */ void home( ); /* Goto origin of spiral */ void set_pitch( ); /* Prompt & set pitch size */ void set_dtime( ); /* Prompt & set dwell time */ void check_vals( ); /* Check pitch & dwell time. */ void help( ); /* Print help screen. */ void type( char *text ); /* Prints the text. */ /* should be int32 */ int keywait( ); /* Pause for microseconds */ /* or until a key is pressed. */ /*******************************************************************/ void main(argc, argv ) int argc; char *argv[]; { tinfo = get_tinfo(); tty = STDIN_FILENO; PADDLE_STATUS = PADDLE_LOCAL; setraw( tty ); home_ha = OFFSET_HA; /* Record home position. */ home_dec = OFFSET_DEC; paused_ha = OFFSET_HA; /* Record paused position */ paused_ha = OFFSET_HA; if ( argc == 3 ) /* Check for command line parameters. */ { sscanf( argv[ 1 ], "%lf", &pitch ); sscanf( argv[ 2 ], "%lf", &dtime ); go( ); /* If they are OK, ready for motion. */ } else /* Otherwise, use default values. */ /* should be int32 */ iwait = ( int ) ( timefactor * dtime ); good_vals = 1; sprintf(tbuf, "\rType \"?\" for help, \"g\" to start, \"q\" to quit.\n"); type(tbuf); sprintf(tbuf, "\r\"Diameter/2\" =%8.1lf OFFSETS: %8.1lf %8.1lf >", ( 0.5 * pitch * (double) size), 3600. * OFFSET_HA, 3600. * OFFSET_DEC ); type(tbuf); spiral( ); /* Do the spiral. */ restore( tty ); type("\n"); } /*************************************************************************/ void spiral( ) { do { if ( keywait(iwait) ) /* Wait iwait milliseconds for a */ do_command(); /* pressed, and execute it. */ if ( moving ) { if (step >= size && for_rev== 1) turn_left( ); if (step <= 0 && for_rev==-1) turn_right( ); if (moving) take_step(); /* Test again -- in case size in now zero */ sprintf(tbuf, "\r\"Diameter/2\" =%8.1lf OFFSETS: %8.1lf %8.1lf >", ( 0.5 * pitch * (double) size), 3600. * OFFSET_HA, 3600. * OFFSET_DEC ); type(tbuf); } } while ( !quit ); } /********************************************************************/ void turn_left( ) /* Turn a corner going forward */ { dir++; /* Turn left */ if (dir>3) dir=0; /* and wrap counter. */ if ( dir==0 || dir==2) /* At these corners */ size++; /* enlarge the size. */ step = 0; /* Motion along new side */ } /********************************************************************/ void turn_right( ) /* Turn a corner going backwards */ { if ( dir==0 || dir==2) /* At above corners */ size--; /* shrink the size. */ dir--; /* Turn right. */ if (dir<0) dir=3; /* and wrap counter. */ step = size; /* For the shrinking spiral, make sure size hasn't gone to 0. */ /* If it has, fix up values and stop motion. */ if (size<=0) { home(); /* At original location; stop */ sprintf(tbuf, " Size=0 STOPPED\n\007"); type(tbuf); } } /************************************************************************/ void take_step( ) /* Move one step in direction specified */ { /* by dir and for_rev */ step += for_rev; if (for_rev==1) degstep = pitch / 3600.; else degstep = - pitch / 3600.; switch (dir) { case 0: OFFSET_HA += degstep; /* Move W one step */ break; case 1: OFFSET_DEC += degstep; /* Move N one step */ break; case 2: OFFSET_HA -= degstep; /* Move E one step */ break; case 3: OFFSET_DEC -= degstep; /* Move S one step */ } } /*******************************************************************/ /* Read in command, and execute it. */ void do_command( ) { /* UNDER UNIX, MUST BE GLOBAL char command; */ /* UNDER UNIX, READ BY ANOTHER SUBROUTINE */ /* command = (char) getche(); */ /* Read key. */ /* Write out command, then backspace over it */ tbuf[0] = command; tbuf[1] = 8; tbuf[2] = 0; type(tbuf); switch ( command ) { case 's' : stop(); break; case 'g' : OFFSET_HA = paused_ha; OFFSET_DEC = paused_dec; moving = 1; break; case 'p' : set_pitch( ); break; case 'h' : home( ); break; case 'q' : quit = 1; break; case 'f' : OFFSET_HA = paused_ha; /* Forward motion */ OFFSET_DEC = paused_dec; for_rev = 1; moving = 1; break; case 'r' : OFFSET_HA = paused_ha; /* Reverse motion */ OFFSET_DEC = paused_dec; for_rev = -1; moving = 1; break; case 't' : set_dtime( ); break; case '?' : help( ); break; case 'z' : OFFSET_HA = paused_ha = home_ha = 0.; /* Zero offsets */ OFFSET_DEC = paused_dec = home_dec = 0.; moving = 0; size = 1; step = 0; dir = 0; for_rev = 1; break; case '2' : if (!moving) OFFSET_DEC -= (pitch/3600.)/2.; break; case '6' : if (!moving) OFFSET_HA += (pitch/3600.)/2.; break; case '4' : if (!moving) OFFSET_HA -= (pitch/3600.)/2.; break; case '8' : if (!moving) OFFSET_DEC += (pitch/3600.)/2.; break; default : sprintf(tbuf, "?\b\a"); /* Invalid character */ type(tbuf); } sprintf(tbuf, "\r\"Diameter/2\" =%8.1lf OFFSETS: %8.1lf %8.1lf >", ( 0.5 * pitch * (double) size), 3600. * OFFSET_HA, 3600. * OFFSET_DEC ); type(tbuf); } /**********************************************************************/ void home( ) { moving = 0; /* Stop motion */ OFFSET_HA = paused_ha = home_ha; /* Go back to original location */ OFFSET_DEC = paused_dec = home_dec; size = 1; step = 0; dir = 0; for_rev = 1; } /*********************************************************************/ void go( ) { check_vals( ); if ( good_vals ) moving = 1; } /*********************************************************************/ void stop(void) { moving = 0; paused_ha = OFFSET_HA; /* Record home position. */ paused_dec = OFFSET_DEC; } /*********************************************************************/ void set_pitch( ) { moving = 0; /* Stop motion */ restore(tty); sprintf(tbuf, "\nEnter new pitch: " ); type(tbuf); scanf( "%lf", &pitch ); setraw(tty); check_vals( ); } /*********************************************************************/ void set_dtime( ) { moving = 0; /* Stop motion */ restore(tty); sprintf(tbuf, "\nEnter new dwell time: " ); type(tbuf); scanf( "%lf", &dtime ); setraw(tty); check_vals( ); } /**********************************************************************/ void check_vals( ) { good_vals = 0; if ( pitch <= 0 || dtime <= 0 ) { sprintf( tbuf, "\nERROR: D_Time and Pitch must be > 0.0\n" ); type(tbuf); } else if ( dtime < 0.2 ) { sprintf(tbuf, "\nERROR: Minimum dwell time = 0.2 sec.\n" ); type(tbuf); } else if ( pitch > 60.01) { fprintf(tbuf, "\nERROR: Maximum pitch size = 60\"\n" ); type(tbuf); } else { good_vals = 1; /* should be int32 */ iwait = ( int ) ( timefactor * dtime ); sprintf(tbuf, "Pitch = %6.1lf \". Dwell time = %6.1lf seconds.\n>", pitch , dtime ); type(tbuf); } } /********************************************************************/ void help( ) { moving = 0; restore(tty); type( "\n----------------------------------------------------------------"); type( "\nSPIRAL [pitch] [time/point]\n" ); type( "moves the telescope in an expanding \"square\" spiral. If you "); type( "enter the optional \nparameters then the spiral starts immediately."); type( " If not, you must start it with \nthe \"g\" command. "); type( "The pitch sets the spacing between turns of the spiral AND "); type( "\nthe step size along the spiral. "); type( "The dwell time sets the delay after each step.\n"); type( "The default pitch is 5.0\" and "); type( "the default dwell time is 0.5 seconds.\n"); type( "Other commands are:\n"); type( "g - Go Start the spiral motion.\n"); type( "f - Forward Start forward expanding motion.\n" ); type( "r - Reverse Start reverse contracting motion.\n"); type( "q - Quit Exit, leaving telescope at current position.\n\n" ); type( "s - Stop Stop in current position and wait.\n" ); type( "h - Home Go to pre-spiral position and wait.\n" ); type( "z - Zero Go to offset 0, 0 and wait.\n"); type( "cursor-keys or Lets you search manually while paused. The spiral\n"); type( " 8462 will resume at the place where you paused.\n\n"); type( "t - dwell Time Set dwell time -- 0.1 to 60. seconds/point.\n"); type( "p - Pitch Set pitch, -- 0.0 to 60. arcseconds.\n"); type( "? - help Display this screen\n" ); usleep(1000000); setraw(tty); } /******************** Unix SPECIFIC ROUTINE. ******************************/ /* If the spiral is running, wait a given number of microseconds for a */ /* key to be pressed. If a key has been pressed, exit the wait loop */ /* immediately, and return 1. If a key has not been pressed by the */ /* end of that time, return 0. */ /* If the spiral is paused, wait till a key is pressed. If it is a */ /* cursor key, convert it from VT100 cursor codes to 8426, for paddle. */ /***************************************************************************/ /* Should be int32 */ int keywait( microsec) int microsec; { int cc; /* Character read. */ int khit; /* True if key has been hit. */ if (moving) { /* Wait for timeout or character */ cc=0; /* astpause( -1, millisec ); */ usleep(microsec); /* Lynxos version. */ cc = read( STDIN_FILENO, commandbuf, 1 ); command = commandbuf[0]; /* Fix for Lynxos "read" bug. */ if (cc == 1) /* Wont read just one byte. */ khit = 1; else khit = 0; return khit; } else { /* Wait for character */ usleep(20000); /* Wait 20 ms. */ do { cc=read(STDIN_FILENO, commandbuf, 1); } while (cc<= 0); command = commandbuf[0]; if (command != 27) return 1; /* If it was an escape, see if it is a VT100 cursor key sequence. */ /* If so, convert it into an 8-4-2-6 key. */ /* The following contains a fix for the Lynxos "read" bug. That */ /* routine reads all three bytes of the escape sequence, even */ /* though I only request one byte at a time. Therefore, read */ /* the data into a bigger buffer, and parse it. */ /* NOTE: If you enter characters to quickly, it is possible */ /* that this kludge fix will get confused. It relies */ /* uppon nrd=1 or nrd=3. */ if (cc == 3) { if (commandbuf[1] != '[') return 1; /* Not cursor sequence? */ command = commandbuf[2]; } else { /* This is the code that SHOULD execute */ /* if it were not for the Lynxos bug. */ while ( read(STDIN_FILENO, &command, 1) != 1); /* Get next char */ if (command != '[') return 1; /* Not cursor? */ while ( read(STDIN_FILENO, &command, 1) != 1); /* Get next char */ } switch (command) { /* Cursor cmd? */ case 'A' : command = '8'; /* A -> 8 */ break; case 'B' : command = '2'; /* B -> 2 */ break; case 'C' : command = '6'; /* C -> 6 */ break; case 'D' : command = '4'; /* D -> 4 */ break; } return 1; } } /********************** Terminal control routines ***************************/ static struct termio term, termsave; /* State of the terminal */ /************** Set terminal to RAW, character at a time, mode ***************/ setraw ( int terminal ) { if (tcgetattr(terminal, &term) < 0) { printf("Could not get terminal structure, to set terminal to raw mode."); exit(1); } termsave = term; /* Save original settings, to restore at end */ /* usleep(1); */ term.c_iflag &= ~IGNCR; /* CR is not deleted from input stream */ term.c_iflag &= ~ICRNL; /* do NOT turn CR into NULL */ term.c_iflag &= ~INLCR; /* do NOT convert NL to CR */ term.c_iflag &= ~INPCK; /* disable parity checking */ term.c_iflag &= ~ISTRIP; /* Do NOT strip parity bits */ term.c_iflag &= ~IGNBRK; /* Ignore break condition on line */ term.c_iflag &= ~IXON; /* Turn OFF XON/XOFF flow control for input */ term.c_iflag &= ~IXOFF; /* Trun OFF XON/XOFF flow control for output */ term.c_cflag |= CLOCAL; /* Ignore modem control lines */ term.c_cflag |= CREAD; /* Enable reading characters */ term.c_cflag |= CSTOPB; /* two stop bits */ term.c_cflag |= CS8; /* Set 8 bits per byte */ term.c_cflag &= ~PARENB; /* Disable parity checking */ term.c_cflag &= ~HUPCL; /* Do not terminate on hangup */ term.c_lflag &= ~ICANON; /* Non- canonical mode - "raw" */ term.c_lflag &= ~ECHO; /* No echo back to terminal */ term.c_lflag &= ~ISIG; /* NO special characters, like SUSP */ term.c_lflag &= ~IEXTEN; /* NO special characters */ term.c_cc[VMIN] = 0; /* No not wait for characters. */ term.c_cc[VTIME] = 0; /* immediately. */ if ( 0 != tcsetattr(terminal,TCSADRAIN,&term)){ printf("Could not set terminal to raw mode."); } } /************ Restore terminal to original (cooked) mode *************/ restore(int terminal) { if ( 0 != tcsetattr(terminal,TCSAFLUSH,&termsave)) { /* I'm not sure this can be printed if call fails. Try anyway. */ printf("Could not restore original terminal mode."); exit(1); } } /**********************************************************************/ void type(char *text) { write(STDOUT_FILENO, text, strlen(text) ); }