Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

keystick.cc

Go to the documentation of this file.
00001 /*
00002   keystick.cc
00003 
00004   Curses-based keyboard control panel
00005 
00006   Modification history:
00007 
00008   17-Aug-1999  FMP took out EMC_TASK_INTERP_STEPPING
00009   21-May-1999  FMP added EMC_LOG_TYPE_TRAJ_POS, changing TRAJ_INPOS,OUTPOS
00010   to AXES_INPOS,OUTPOS
00011   22-Mar-1999  FMP added line to emc_task_plan_run_msg
00012   7-Feb-1999  FMP added EMC_LOG_TYPE_TRAJ_FERROR
00013   13-Jan-1999  FMP added -noerror and corresponding catchErrors flag to
00014   disable reading of error buffer, so other GUIs can be the ones that
00015   get to display the errors; took out resetting of emcCommandSerialNumber
00016   from EMC status, since this caused some rapid-fire commands to not be seen.
00017   7-Jan-1999  FMP added errorFp for error logging
00018   29-Dec-1998  FMP added F6 for sending EMC_TASK_PLAN_INIT; fixed bug that
00019   prevented fkeys and escape to be seen when user was typing interactively.
00020   23-Dec-1998  FMP added [AXIS_#] JOGGING_POLARITY to set the directions
00021   for the arrow jogging keys
00022   4-Dec-1998  FMP added program screen "progwin"
00023   21-Oct-1998  FMP checked for 'window' to be non-NULL in printError() before
00024   printing; added EMC_COMMAND_TIMEOUT,DELAY instead of task cycle time ini
00025   file var in emcCommandWait()
00026   16-Oct-1998  FMP added confirm to quit; changed to new EMC_OPERATOR_ERROR
00027   operator messages; made 'quit()' actually clean up so blocking read won't
00028   hang program
00029   9-Oct-1998  FMP converted jog speed to units/min
00030   5-Oct-1998  FMP added lube control; [DISPLAY] ini file reading; command
00031   serial numbers in diagwin
00032   1-Oct-1998  FMP added lube status bar; cmd/act pos display
00033   23-Sep-1998  FMP changed connect name to keystick, from emcpanel
00034   1-Sep-1998  FMP inhibited multi-axis jogs; added limit '*' to XYZ display
00035   20-Aug-1998  FMP added EMCMOT_LOG_TYPE_AXIS_VEL to logging
00036   3-Aug-1998  FMP added tool length offset on display; subtracted from Z
00037   value
00038   31-Jul-1998  FMP added G and M codes; recall last MDI line; printed
00039   toolInSpindle
00040   10-Jul-1998  FMP added emcCommandWait after all emc writes
00041   30-Jun-1998  FMP added programPrefix; TRAJ_MAX_VELOCITY check against
00042   jogSpeed
00043   29-Jun-1998  FMP corrected spindle incr/decr labels, added string for
00044   spindle increase/decrease state
00045   26-Jun-1998  FMP changed fkeys to get rid of tab toggling for spindle
00046   and coolant
00047   22-Jun-1998  FMP converted keyup delays from units of cycles to actual
00048   microseconds
00049   17-Jun-1998  FMP added startTimer, 'which' value to EMC_LOG_OPEN
00050   16-Jun-1998  FMP added logging
00051   15-Jun-1998  FMP added program line number and line text printing;
00052   dump mode
00053   12-Jun-1998  FMP fixed mist and flood labels to match what keys do
00054   11-Jun-1998  FMP added window size getting that works; loading and
00055   printing tool table
00056   10-Jun-1998  FMP added multiple status screens, modal info limiting
00057   9-Jun-1998  FMP created from non-curses based raw keyboard program
00058 */
00059 
00060 #include <stdio.h>
00061 #include <string.h>
00062 #include <stdlib.h>
00063 #include <ctype.h>
00064 #include <signal.h>
00065 #include <errno.h>
00066 #include <sys/time.h>           // struct itimerval
00067 #include <sys/ioctl.h>          // ioctl(), TIOCGWINSZ, struct winsize
00068 #include <unistd.h>             // STDIN_FILENO
00069 
00070 #include "rcs.hh"               // rcs_print_error(), esleep()
00071 #include "emc.hh"               // EMC NML
00072 #include "emcglb.h"             // EMC_NMLFILE, TRAJ_MAX_VELOCITY
00073 #include "emccfg.h"             // DEFAULT_TRAJ_MAX_VELOCITY
00074 #include "inifile.h"            // INIFILE
00075 
00076 #include <curses.h>
00077 #define ESC 27
00078 #define TAB 9
00079 #define RETURN 13
00080 #define ALT(ch) ((ch) + 128)
00081 #define CTL(ch) ((ch) - 64)
00082 
00083 // paths to awk and xgraph, using to plot logs
00084 // fill these in for your system, if these are not in user's path
00085 #define AWK_PATH "awk"
00086 #define XGRAPH_PATH "xgraph"
00087 #define SYSTEM_STRING_LEN 1024
00088 
00089 static int plotLog(const char * logfile, int logtype, int which)
00090 {
00091   char string[SYSTEM_STRING_LEN];
00092   int retval;
00093 
00094   if (logfile == 0)
00095     {
00096       return -1;
00097     }
00098 
00099   switch (logtype)
00100     {
00101     case EMC_LOG_TYPE_AXIS_POS:
00102     case EMC_LOG_TYPE_AXIS_VEL:
00103       sprintf(string, "( %s '{print $1 \" \" $2}' < %s ; echo \"\" ; %s '{print $1 \" \" $3}' < %s ) 2> /dev/null | %s -m 1> /dev/null 2> /dev/null", AWK_PATH, logfile, AWK_PATH, logfile, XGRAPH_PATH);
00104       break;
00105 
00106     case EMC_LOG_TYPE_AXES_INPOS:
00107     case EMC_LOG_TYPE_AXES_OUTPOS:
00108       sprintf(string, "%s '{print $2 \" \" $3}' < %s 2> /dev/null | %s -m 1> /dev/null 2> /dev/null", AWK_PATH, logfile, XGRAPH_PATH);
00109       break;
00110 
00111     case EMC_LOG_TYPE_AXES_FERROR:
00112       /* we want to compose:
00113          ( awk '{print $1 " " $2}' < emc.log ; echo "" ; awk '{print $1 " " $3}' < emc.log ; echo "" ; awk '{print $1 " " $4}' < emc.log ) 2> /dev/null | xgraph -m 1> /dev/null 2> /dev/null"
00114        */
00115       sprintf(string, "( %s '{print $1 \" \" $2}' < %s ; echo \"\" ; %s '{print $1 \" \" $3}' < %s ; echo \"\" ; %s '{print $1 \" \" $4}' < %s ) 2> /dev/null | %s -m 1> /dev/null 2> /dev/null", AWK_PATH, logfile, AWK_PATH, logfile, AWK_PATH, logfile, XGRAPH_PATH);
00116       break;
00117 
00118     default:
00119       return -1;
00120       break;
00121     }
00122 
00123   retval = system(string);
00124 
00125   return retval;
00126 }
00127 
00128 // the NML channels to the EMC task
00129 static RCS_CMD_CHANNEL *emcCommandBuffer = 0;
00130 static RCS_STAT_CHANNEL *emcStatusBuffer = 0;
00131 EMC_STAT *emcStatus = 0;
00132 
00133 // the NML channel for errors
00134 static NML *emcErrorBuffer = 0;
00135 static char error_string[EMC_OPERATOR_ERROR_LEN] = "";
00136 
00137 // the current command numbers, set up updateStatus(), used in main()
00138 static int emcCommandSerialNumber = 0;
00139 
00140 // NML messages
00141 static EMC_AXIS_HOME emc_axis_home_msg;
00142 static EMC_AXIS_ABORT emc_axis_abort_msg;
00143 static EMC_AXIS_JOG emc_axis_jog_msg;
00144 static EMC_AXIS_INCR_JOG emc_axis_incr_jog_msg;
00145 static EMC_TRAJ_SET_SCALE emc_traj_set_scale_msg;
00146 static EMC_TRAJ_ABORT emc_traj_abort_msg;
00147 static EMC_SPINDLE_ON emc_spindle_on_msg;
00148 static EMC_SPINDLE_OFF emc_spindle_off_msg;
00149 static EMC_SPINDLE_INCREASE emc_spindle_increase_msg;
00150 static EMC_SPINDLE_DECREASE emc_spindle_decrease_msg;
00151 static EMC_SPINDLE_CONSTANT emc_spindle_constant_msg;
00152 static EMC_SPINDLE_BRAKE_RELEASE emc_spindle_brake_release_msg;
00153 static EMC_SPINDLE_BRAKE_ENGAGE emc_spindle_brake_engage_msg;
00154 static EMC_COOLANT_MIST_ON emc_coolant_mist_on_msg;
00155 static EMC_COOLANT_MIST_OFF emc_coolant_mist_off_msg;
00156 static EMC_COOLANT_FLOOD_ON emc_coolant_flood_on_msg;
00157 static EMC_COOLANT_FLOOD_OFF emc_coolant_flood_off_msg;
00158 static EMC_LUBE_ON emc_lube_on_msg;
00159 static EMC_LUBE_OFF emc_lube_off_msg;
00160 static EMC_TOOL_LOAD_TOOL_TABLE emc_tool_load_tool_table_msg;
00161 static EMC_TASK_SET_MODE mode_msg;
00162 static EMC_TASK_SET_STATE state_msg;
00163 static EMC_TASK_ABORT task_abort_msg;
00164 static EMC_TASK_PLAN_INIT task_plan_init_msg;
00165 static EMC_TASK_PLAN_OPEN task_plan_open_msg;
00166 static EMC_TASK_PLAN_RUN task_plan_run_msg;
00167 static EMC_TASK_PLAN_EXECUTE task_plan_execute_msg;
00168 static EMC_TASK_PLAN_PAUSE task_plan_pause_msg;
00169 static EMC_TASK_PLAN_RESUME task_plan_resume_msg;
00170 static EMC_TASK_PLAN_STEP task_plan_step_msg;
00171 static EMC_LOG_OPEN emc_log_open_msg;
00172 static EMC_LOG_START emc_log_start_msg;
00173 static EMC_LOG_STOP emc_log_stop_msg;
00174 static EMC_LOG_CLOSE emc_log_close_msg;
00175 
00176 // critical section flag-- set to non-zero to prevent sig handler
00177 // from interrupting your window printing
00178 static unsigned char critFlag = 0;
00179 
00180 // the program path prefix
00181 static char programPrefix[EMC_TASK_FILENAME_LEN] = "";
00182 // the saved program name
00183 static char programFile[EMC_TASK_FILENAME_LEN] = "";
00184 static int programOpened = 0;
00185 static FILE * programFp = 0;
00186 static int programFpLine = 0;
00187 static int programActiveLine = 0;
00188 static char programLineText[EMC_TASK_COMMAND_LEN] = "";
00189 
00190 // saved log file params
00191 static char saveLogFile[EMC_LOG_FILENAME_LEN] = "emc.log";
00192 static int saveLogType = EMC_LOG_TYPE_AXIS_POS;
00193 static int saveLogSize = 1000;
00194 static int saveLogSkip = 0;
00195 static int saveLogAxis = 0;
00196 
00197 // error log file
00198 static FILE *errorFp = NULL;
00199 #define ERROR_FILE "keystick.err"
00200 
00201 typedef enum {
00202   JOG_CONTINUOUS = 1,
00203   JOG_INCREMENTAL
00204 } JOG_MODE;
00205 
00206 static JOG_MODE jogMode
00207  = JOG_CONTINUOUS;
00208 static double jogIncrement = 0.001;
00209 static double jogSpeed = 60.0;
00210 
00211 static int xJogPol = 1;
00212 static int yJogPol = 1;
00213 static int zJogPol = 1;
00214 
00215 typedef enum {
00216   AXIS_NONE = 1,
00217   AXIS_X,
00218   AXIS_Y,
00219   AXIS_Z
00220 } AXIS_TYPE;
00221 
00222 static AXIS_TYPE axisSelected = AXIS_X;
00223 static AXIS_TYPE axisJogging = AXIS_NONE;
00224 
00225 static const char * axisString(AXIS_TYPE a)
00226 {
00227   switch (a)
00228     {
00229     case AXIS_X:
00230       return "    X SELECTED    ";
00231     case AXIS_Y:
00232       return "    Y SELECTED    ";
00233     case AXIS_Z:
00234       return "    Z SELECTED    ";
00235     default:
00236       return "    ? SELECTED    ";
00237     }
00238 }
00239 
00240 static int axisIndex(AXIS_TYPE a)
00241 {
00242   if (a == AXIS_X)
00243     return 0;
00244   if (a == AXIS_Y)
00245     return 1;
00246   if (a == AXIS_Z)
00247     return 2;
00248 
00249   return 0;
00250 }
00251 
00252 typedef enum {
00253   COORD_RELATIVE = 1,
00254   COORD_ABSOLUTE
00255 } COORD_TYPE;
00256 
00257 static COORD_TYPE coords = COORD_RELATIVE;
00258 
00259 typedef enum {
00260   POS_DISPLAY_ACT = 1,
00261   POS_DISPLAY_CMD
00262 } POS_DISPLAY_TYPE;
00263 
00264 static POS_DISPLAY_TYPE posDisplay = POS_DISPLAY_ACT;
00265 
00266 static int spindleChanging = 0;
00267 
00268 #define INTERRUPT_USECS 50000
00269 static int usecs = INTERRUPT_USECS;
00270 
00271 static chtype ch = 0, oldch = 0;
00272 
00273 #define LINELEN 80
00274 static char line_blank[LINELEN + 1];
00275 
00276 static char scratch_string[LINELEN] = "";
00277 static char state_string[LINELEN] = "";
00278 static char mode_string[LINELEN] = "";
00279 static char spindle_string[LINELEN] = "";
00280 static char brake_string[LINELEN] = "";
00281 static char mist_string[LINELEN] = "";
00282 static char flood_string[LINELEN] = "";
00283 static char lube_on_string[LINELEN] = "";
00284 static char lube_level_string[LINELEN] = "";
00285 static char home_string[LINELEN] = "";
00286 static char pos_string[LINELEN] = "";
00287 static char origin_string[LINELEN] = "";
00288 static char speed_string[LINELEN] = "";
00289 static char incr_string[LINELEN] = "";
00290 static char prog_string[LINELEN] = "";
00291 static char line_string[LINELEN] = "";
00292 static char interp_string[LINELEN] = "";
00293 static char active_g_codes_string[LINELEN] = "";
00294 static char active_m_codes_string[LINELEN] = "";
00295 
00296 // bottom string gill be set to "---Machine Version---"
00297 static char bottom_string[LINELEN + 1] = "";
00298 
00299 // key repeat delays, in microseconds
00300 #define DEFAULT_FIRST_KEYUP_DELAY 300000 // works w/ 50000 alarm
00301 static int FIRST_KEYUP_DELAY = DEFAULT_FIRST_KEYUP_DELAY;
00302 #define DEFAULT_NEXT_KEYUP_DELAY  100000 // works w/ 50000 alarm
00303 static int NEXT_KEYUP_DELAY = DEFAULT_NEXT_KEYUP_DELAY;
00304 
00305 static int keyup_count = 0;
00306 
00307 static enum {DIAG_USECS = 1, DIAG_FIRST_KEYUP_DELAY, DIAG_NEXT_KEYUP_DELAY} diagtab = DIAG_USECS;
00308 
00309 static enum {LOG_TYPE = 1, LOG_SIZE, LOG_SKIP, LOG_AXIS} logtab = LOG_TYPE;
00310 
00311 static WINDOW * window = 0;
00312 static WINDOW * helpwin = 0;
00313 static WINDOW * diagwin = 0;
00314 static WINDOW * toolwin = 0;
00315 static WINDOW * logwin = 0;
00316 static WINDOW * progwin = 0;
00317 
00318 static int wbegy, wbegx;
00319 static int wmaxy, wmaxx;
00320 
00321 static void printFkeys()
00322 {
00323   wattrset(window, A_BOLD);
00324   mvwaddstr(window, 0, 1,  "F1 ");
00325   mvwaddstr(window, 1, 1,  "F2 ");
00326   mvwaddstr(window, 2, 1,  "F3 ");
00327   mvwaddstr(window, 3, 1,  "F4 ");
00328   mvwaddstr(window, 0, 21, "F5 ");
00329   mvwaddstr(window, 1, 21, "F6 ");
00330   mvwaddstr(window, 2, 21, "F7 ");
00331   mvwaddstr(window, 3, 21, "F8 ");
00332   mvwaddstr(window, 0, 41, "F9 ");
00333   mvwaddstr(window, 1, 41, "F10");
00334   mvwaddstr(window, 2, 41, "F11");
00335   mvwaddstr(window, 3, 41, "F12");
00336   mvwaddstr(window, 0, 61, "ESC");
00337   mvwaddstr(window, 1, 61, "TAB");
00338   mvwaddstr(window, 2, 61, "END");
00339   mvwaddstr(window, 3, 61, " ? ");
00340 
00341   wattrset(window, 0);
00342   mvwaddstr(window, 0, 5,      "Estop On/Off  ");
00343   mvwaddstr(window, 1, 5,      "Machine On/Off");
00344   mvwaddstr(window, 2, 5,      "Manual Mode   ");
00345   mvwaddstr(window, 3, 5,      "Auto Mode     ");
00346 
00347   mvwaddstr(window, 0, 25,     "MDI Mode      ");
00348   mvwaddstr(window, 1, 25,     "Reset Interp  ");
00349   mvwaddstr(window, 2, 25,     "Mist On/Off   ");
00350   mvwaddstr(window, 3, 25,     "Flood On/Off  ");
00351 
00352   mvwaddstr(window, 0, 45,     "Spndl Fwd/Off ");
00353   mvwaddstr(window, 1, 45,     "Spndl Rev/Off ");
00354   mvwaddstr(window, 2, 45,     "Spndl Decrease");
00355   mvwaddstr(window, 3, 45,     "Spndl Increase");
00356 
00357   mvwaddstr(window, 0, 65,     "Aborts Actions");
00358   mvwaddstr(window, 1, 65,     "Selects Params");
00359   mvwaddstr(window, 2, 65,     "Quits Display ");
00360   mvwaddstr(window, 3, 65,     "Toggles Help  ");
00361 }
00362 
00363 #define ERR_Y ((wmaxy) - 2)
00364 #define ERR_X (wbegx)
00365 
00366 static void clearWindow()
00367 {
00368   int t;
00369 
00370   critFlag = 1;
00371 
00372   wattrset(window, A_BOLD);
00373   for (t = wbegy; t <= wmaxy; t++)
00374     {
00375       mvwaddstr(window, t, 0, line_blank);
00376     }
00377   wrefresh(window);
00378 
00379   wattrset(window, 0);
00380   for (t = wbegy; t <= wmaxy; t++)
00381     {
00382       mvwaddstr(window, t, 0, line_blank);
00383     }
00384   wmove(window, wmaxy, wbegx);
00385   wrefresh(window);
00386 
00387   critFlag = 0;
00388 }
00389 
00390 static void printError(const char * errstring)
00391 {
00392   int savey, savex;
00393   chtype saveattr;
00394 
00395   // log to error file
00396   if (NULL != errorFp)
00397     {
00398       fprintf(errorFp, "%f\t%s\n", etime(), errstring);
00399     }
00400 
00401   if (0 == window)
00402     {
00403       // no window yet
00404       return;
00405     }
00406 
00407   critFlag = 1;
00408 
00409   getyx(window, savey, savex);
00410   saveattr = getattrs(window);
00411 
00412   mvwaddstr(window, ERR_Y, ERR_X, line_blank);
00413   wattrset(window, A_BOLD);
00414   mvwaddstr(window, ERR_Y, ERR_X, errstring);
00415   wattrset(window, (int) saveattr);
00416   wmove(window, savey, savex);
00417   wrefresh(window);
00418 
00419   critFlag = 0;
00420 }
00421 
00422 static void printStatus()
00423 {
00424   int savey, savex;
00425   int t;
00426   int line;
00427   int override;
00428   int len;
00429   int code;
00430 
00431   getyx(window, savey, savex);
00432 
00433   if (window == helpwin)
00434     {
00435       printFkeys();
00436 
00437       wattrset(window, 0);
00438       mvwaddstr(window, 5, 1, "x/X y/Y z/Z");
00439       mvwaddstr(window, 6, 1, "HOME");
00440       mvwaddstr(window, 7, 1, "< > or , .");
00441       mvwaddstr(window, 8, 1, "1-9, 0");
00442       mvwaddstr(window, 9, 1, "<- arrow keys ->");
00443       mvwaddstr(window, 10, 1, "^ arrow keys V");
00444       mvwaddstr(window, 11, 1, "PageUp/PageDown");
00445       mvwaddstr(window, 12, 1, "c/C");
00446       mvwaddstr(window, 13, 1, "i/I");
00447       mvwaddstr(window, 14, 1, "#");
00448       mvwaddstr(window, 15, 1, "@");
00449 
00450       wattrset(window, A_UNDERLINE);
00451       mvwaddstr(window, 5, 19, "selects axis");
00452       mvwaddstr(window, 6, 19, "homes selected axis");
00453       mvwaddstr(window, 7, 19, "change jog speed");
00454       mvwaddstr(window, 8, 19, "10%-90%, 100% feed");
00455       mvwaddstr(window, 9, 19, "jog X");
00456       mvwaddstr(window, 10, 19, "jog Y");
00457       mvwaddstr(window, 11, 19, "jog Z");
00458       mvwaddstr(window, 12, 19, "sets continuous jog");
00459       mvwaddstr(window, 13, 19, "toggles incr jog");
00460       mvwaddstr(window, 14, 19, "toggles abs/rel");
00461       mvwaddstr(window, 15, 19, "toggles cmd/act");
00462 
00463       wattrset(window, 0);
00464       mvwaddstr(window, 5, 41, "B");
00465       mvwaddstr(window, 6, 41, "b");
00466       mvwaddstr(window, 7, 41, "o/O");
00467       mvwaddstr(window, 8, 41, "r/R");
00468       mvwaddstr(window, 9, 41, "p/P");
00469       mvwaddstr(window, 10, 41, "s/S");
00470       mvwaddstr(window, 11, 41, "quote/XYZGM");
00471       mvwaddstr(window, 12, 41, "l/L");
00472       mvwaddstr(window, 13, 41, "u/U");
00473 
00474       wattrset(window, A_UNDERLINE);
00475       mvwaddstr(window, 5, 54, "turns spindle brake on");
00476       mvwaddstr(window, 6, 54, "turns spindle brake off");
00477       mvwaddstr(window, 7, 54, "prompts for program");
00478       mvwaddstr(window, 8, 54, "runs selected program");
00479       mvwaddstr(window, 9, 54, "pauses motion");
00480       mvwaddstr(window, 10, 54, "starts motion again");
00481       mvwaddstr(window, 11, 54, "prompts for MDI command");
00482       mvwaddstr(window, 12, 54, "prompts for tool table");
00483       mvwaddstr(window, 13, 54, "turns lube off/on");
00484 
00485       if (error_string[0] != 0)
00486         {
00487           printError(error_string);
00488         }
00489 
00490       wattrset(window, A_REVERSE);
00491       mvwaddstr(window, wmaxy - 1, wbegx, bottom_string);
00492       wattrset(window, 0);
00493 
00494       // restore cursor position
00495       wmove(window, savey, savex);
00496       wrefresh(window);
00497     }
00498   else if (window == diagwin)
00499     {
00500       wattrset(window, A_BOLD);
00501       mvwaddstr(window, 0, 34, "Diagnostics");
00502 
00503       wattrset(window, 0);
00504       mvwaddstr(window, 2, 1, "Task Heartbeat/Cmd:");
00505       mvwaddstr(window, 3, 1, "IO Heartbeat/Cmd:");
00506       mvwaddstr(window, 4, 1, "Motion Heartbeat/Cmd:");
00507 
00508       if (diagtab == DIAG_USECS)
00509           wattrset(window, A_BOLD);
00510       mvwaddstr(window, 6, 1,  "Polling Period (usecs):");
00511       wattrset(window, 0);
00512       if (diagtab == DIAG_FIRST_KEYUP_DELAY)
00513           wattrset(window, A_BOLD);
00514       mvwaddstr(window, 7, 1, "Kbd Delay Until Repeat:");
00515       wattrset(window, 0);
00516       if (diagtab == DIAG_NEXT_KEYUP_DELAY)
00517           wattrset(window, A_BOLD);
00518       mvwaddstr(window, 8, 1, "Kbd Delay Between Repeats:");
00519       wattrset(window, 0);
00520 
00521       mvwaddstr(window, 10, 1, "Task Execution State:");
00522 
00523       mvwaddstr(window, 12, 1, "Traj Scale:");
00524       mvwaddstr(window, 13, 1, "X Scale:");
00525       mvwaddstr(window, 14, 1, "Y Scale:");
00526       mvwaddstr(window, 15, 1, "Z Scale:");
00527 
00528       mvwaddstr(window, 17, 1, "V/Max V:");
00529       mvwaddstr(window, 18, 1, "A/Max A:");
00530 
00531       wattrset(window, A_UNDERLINE);
00532 
00533       sprintf(scratch_string, "%10d %10d %10d", emcStatus->task.heartbeat,
00534               emcStatus->echo_serial_number,
00535               emcStatus->status);
00536       mvwaddstr(window, 2, 28, scratch_string);
00537       sprintf(scratch_string, "%10d %10d", emcStatus->io.heartbeat,
00538               emcStatus->io.echo_serial_number);
00539       mvwaddstr(window, 3, 28, scratch_string);
00540       sprintf(scratch_string, "%10d %10d", emcStatus->motion.heartbeat,
00541               emcStatus->motion.echo_serial_number);
00542       mvwaddstr(window, 4, 28, scratch_string);
00543 
00544       sprintf(scratch_string, "%10d", usecs);
00545       mvwaddstr(window, 6, 28, scratch_string);
00546       sprintf(scratch_string, "%10d", FIRST_KEYUP_DELAY);
00547       mvwaddstr(window, 7, 28, scratch_string);
00548       sprintf(scratch_string, "%10d", NEXT_KEYUP_DELAY);
00549       mvwaddstr(window, 8, 28, scratch_string);
00550 
00551       sprintf(scratch_string, "%10d", emcStatus->task.execState);
00552       mvwaddstr(window, 10, 28, scratch_string);
00553 
00554       sprintf(scratch_string, "%10.3f", emcStatus->motion.traj.scale);
00555       mvwaddstr(window, 12, 28, scratch_string);
00556       sprintf(scratch_string, "%10.3f", emcStatus->motion.axis[0].scale);
00557       mvwaddstr(window, 13, 28, scratch_string);
00558       sprintf(scratch_string, "%10.3f", emcStatus->motion.axis[1].scale);
00559       mvwaddstr(window, 14, 28, scratch_string);
00560       sprintf(scratch_string, "%10.3f", emcStatus->motion.axis[2].scale);
00561       mvwaddstr(window, 15, 28, scratch_string);
00562 
00563       sprintf(scratch_string, "%10.3f%10.3f",
00564               emcStatus->motion.traj.velocity, emcStatus->motion.traj.maxVelocity);
00565       mvwaddstr(window, 17, 28, scratch_string);
00566       sprintf(scratch_string, "%10.3f%10.3f",
00567               emcStatus->motion.traj.acceleration, emcStatus->motion.traj.maxAcceleration);
00568       mvwaddstr(window, 18, 28, scratch_string);
00569 
00570       wattrset(window, 0);
00571       if (error_string[0] != 0)
00572         {
00573           printError(error_string);
00574         }
00575 
00576       wattrset(window, A_REVERSE);
00577       mvwaddstr(window, wmaxy - 1, wbegx, bottom_string);
00578       wattrset(window, 0);
00579 
00580       // restore cursor position
00581       wmove(window, savey, savex);
00582       wrefresh(window);
00583     }
00584   else if (window == toolwin)
00585     {
00586       wattrset(window, A_BOLD);
00587       mvwaddstr(window, 0, 34, "Tool Table");
00588 
00589       wattrset(window, 0);
00590       mvwaddstr(window, 2, 1, "Pocket        ID    Length  Diameter");
00591 
00592       wattrset(window, A_UNDERLINE);
00593       line = 4;
00594       for (t = 0; t < CANON_TOOL_MAX; t++)
00595         {
00596           if (emcStatus->io.tool.toolTable[t].id != 0)
00597             {
00598               sprintf(scratch_string, "%4d%10d%10.4f%10.4f",
00599                       t,
00600                       emcStatus->io.tool.toolTable[t].id,
00601                       emcStatus->io.tool.toolTable[t].length,
00602                       emcStatus->io.tool.toolTable[t].diameter);
00603               mvwaddstr(window, line++, 3, scratch_string);
00604             }
00605         }
00606 
00607       wattrset(window, 0);
00608       if (error_string[0] != 0)
00609         {
00610           printError(error_string);
00611         }
00612 
00613       wattrset(window, A_REVERSE);
00614       mvwaddstr(window, wmaxy - 1, wbegx, bottom_string);
00615       wattrset(window, 0);
00616 
00617       // restore cursor position
00618       wmove(window, savey, savex);
00619       wrefresh(window);
00620     }
00621   else if (window == logwin)
00622     {
00623       wattrset(window, A_BOLD);
00624       mvwaddstr(window, 0, 34, "Data Logging");
00625 
00626       wattrset(window, 0);
00627       mvwaddstr(window, 4, 0, line_blank);
00628       mvwaddstr(window, 4, 1,  "File:");
00629 
00630       mvwaddstr(window, 5, 1,  "Points:");
00631 
00632       if (logtab == LOG_TYPE)
00633           wattrset(window, A_BOLD);
00634       mvwaddstr(window, 6, 1,  "Type:");
00635       wattrset(window, 0);
00636 
00637       if (logtab == LOG_SIZE)
00638           wattrset(window, A_BOLD);
00639       mvwaddstr(window, 7, 1, "Size:");
00640       wattrset(window, 0);
00641 
00642       if (logtab == LOG_SKIP)
00643           wattrset(window, A_BOLD);
00644       mvwaddstr(window, 8, 1, "Skip:");
00645       wattrset(window, 0);
00646 
00647       if (saveLogType == EMC_LOG_TYPE_AXIS_POS)
00648         {
00649           if (logtab == LOG_AXIS)
00650             wattrset(window, A_BOLD);
00651           mvwaddstr(window, 9, 1, "Axis:");
00652           wattrset(window, 0);
00653         }
00654       else
00655         {
00656           mvwaddstr(window, 9, 0, line_blank);
00657         }
00658 
00659       wattrset(window, A_UNDERLINE);
00660 
00661       // print open/closed/logging
00662       if (emcStatus->logOpen)
00663         {
00664           wattrset(window, A_REVERSE);
00665           strcpy(scratch_string, " OPEN ");
00666         }
00667       else
00668         {
00669           wattrset(window, A_UNDERLINE);
00670           strcpy(scratch_string, "CLOSED");
00671         }
00672       mvwaddstr(window, 2, 28, scratch_string);
00673 
00674       if (emcStatus->logStarted)
00675         {
00676           wattrset(window, A_REVERSE);
00677           strcpy(scratch_string, "  LOGGING  ");
00678         }
00679       else
00680         {
00681           wattrset(window, A_UNDERLINE);
00682           strcpy(scratch_string, "NOT LOGGING");
00683         }
00684       mvwaddstr(window, 2, 46, scratch_string);
00685 
00686       wattrset(window, A_UNDERLINE);
00687 
00688       // print file string
00689       mvwaddstr(window, 4, 28, saveLogFile);
00690 
00691       // compose and print log point number
00692       sprintf(scratch_string, "%-10d", emcStatus->logPoints);
00693       mvwaddstr(window, 5, 28, scratch_string);
00694 
00695       // compose and print log type
00696       switch (saveLogType)
00697         {
00698         case 0:
00699           strcpy(scratch_string, "                 ");
00700           break;
00701 
00702         case EMC_LOG_TYPE_AXIS_POS:
00703           strcpy(scratch_string, "AXIS INPUT/OUTPUT");
00704           break;
00705 
00706         case EMC_LOG_TYPE_AXES_INPOS:
00707           strcpy(scratch_string, "INPUT POSITION   ");
00708           break;
00709 
00710         case EMC_LOG_TYPE_AXES_OUTPOS:
00711           strcpy(scratch_string, "OUTPUT POSITION  ");
00712           break;
00713 
00714         case EMC_LOG_TYPE_AXIS_VEL:
00715           strcpy(scratch_string, "AXIS CMD/ACT VEL ");
00716           break;
00717 
00718         case EMC_LOG_TYPE_AXES_FERROR:
00719           strcpy(scratch_string, "FOLLOWING ERROR  ");
00720           break;
00721 
00722         default:
00723           sprintf(scratch_string, "%-17d", saveLogType);
00724           break;
00725         }
00726       mvwaddstr(window, 6, 28, scratch_string);
00727 
00728       // compose and print log size
00729       sprintf(scratch_string, "%-10d", saveLogSize);
00730       mvwaddstr(window, 7, 28, scratch_string);
00731 
00732       // compose and print log skip
00733       sprintf(scratch_string, "%-10d", saveLogSkip);
00734       mvwaddstr(window, 8, 28, scratch_string);
00735 
00736       // compose and print log axis
00737       if (saveLogType == EMC_LOG_TYPE_AXIS_POS)
00738         {
00739           sprintf(scratch_string, "%s",
00740                   saveLogAxis == 0 ? "X" :
00741                   saveLogAxis == 1 ? "Y" :
00742                   saveLogAxis == 2 ? "Z" : "?");
00743           mvwaddstr(window, 9, 28, scratch_string);
00744         }
00745 
00746       wattrset(window, 0);
00747       if (error_string[0] != 0)
00748         {
00749           printError(error_string);
00750         }
00751 
00752       wattrset(window, A_REVERSE);
00753       mvwaddstr(window, wmaxy - 1, wbegx, bottom_string);
00754       wattrset(window, 0);
00755 
00756       // restore cursor position
00757       wmove(window, savey, savex);
00758       wrefresh(window);
00759     }
00760   else if (window == progwin)
00761     {
00762       mvwaddstr(window, 0, 0, line_blank);
00763       wattrset(window, A_BOLD);
00764       if (emcStatus->task.file[0] == 0)
00765         {
00766           mvwaddstr(window, 0, 36, "(no program)");
00767         }
00768       else
00769         {
00770           mvwaddstr(window, 0, 36, emcStatus->task.file);
00771         }
00772       wattrset(window, 0);
00773 
00774       if (emcStatus->task.currentLine > 0)
00775         {
00776           if (emcStatus->task.motionLine > 0 &&
00777               emcStatus->task.motionLine < emcStatus->task.currentLine)
00778             {
00779               programActiveLine = emcStatus->task.motionLine;
00780             }
00781           else
00782             {
00783               programActiveLine = emcStatus->task.currentLine;
00784             }
00785 
00786           if (programFp != 0)
00787             {
00788               if (programFpLine > programActiveLine)
00789                 {
00790                   rewind(programFp);
00791                   programFpLine = 0;
00792                   programLineText[0] = 0;
00793                 }
00794 
00795               // fast forward over past lines
00796               while (programFpLine < programActiveLine)
00797                 {
00798                   fgets(programLineText, EMC_TASK_COMMAND_LEN, programFp);
00799                   programFpLine++;
00800                 }
00801 
00802               // now we have the current line
00803               wattrset(window, A_BOLD);
00804               for (t = 0; t < 20; t++)
00805                 {
00806                   // knock off CR, LF
00807                   len = strlen(programLineText) - 1;
00808                   while (len >= 0)
00809                     {
00810                       if (isspace(programLineText[len]))
00811                         {
00812                           programLineText[len] = 0;
00813                           len--;
00814                         }
00815                       else
00816                         {
00817                           break;
00818                         }
00819                     }
00820 
00821                   // print this line
00822                   mvwaddstr(window, t+2, wbegx, line_blank);
00823                   mvwaddstr(window, t+2, wbegx, programLineText);
00824                   wattrset(window, 0);
00825 
00826                   // get the next line
00827                   if (NULL != fgets(programLineText, EMC_TASK_COMMAND_LEN, programFp))
00828                     {
00829                       programFpLine++;
00830                     }
00831                   else
00832                     {
00833                       // make it a blank line to clear any old stuff
00834                       strcpy(programLineText, line_blank);
00835                     }
00836                 }
00837             }
00838           else
00839             {
00840               programLineText[0] = 0;
00841             }
00842         }
00843       else
00844         {
00845           programActiveLine = 0;
00846           programLineText[0] = 0;
00847           line_string[0] = 0;
00848         }
00849 
00850       wattrset(window, 0);
00851       if (error_string[0] != 0)
00852         {
00853           printError(error_string);
00854         }
00855 
00856       wattrset(window, A_REVERSE);
00857       mvwaddstr(window, wmaxy - 1, wbegx, bottom_string);
00858       wattrset(window, 0);
00859 
00860       // restore cursor position
00861       wmove(window, savey, savex);
00862       wrefresh(window);
00863     }
00864   else // if (window == stdscr)
00865     {
00866       // print the function key labels
00867       printFkeys();
00868 
00869       // print the status labels
00870 
00871       wattrset(window, 0);
00872 
00873       mvwaddstr(window, 6, 1, "Override:");
00874       mvwaddstr(window, 7, 1, "Tool:");
00875       mvwaddstr(window, 8, 1, "Offset:");
00876 
00877       mvwaddstr(window, 7, 61, "Speed:");
00878       mvwaddstr(window, 8, 61, "Incr:             ");
00879 
00880       strcpy(scratch_string, "--X--");
00881       if (emcStatus->motion.axis[0].minHardLimit)
00882         scratch_string[0] = '*';
00883       if (emcStatus->motion.axis[0].minSoftLimit)
00884         scratch_string[1] = '*';
00885       if (emcStatus->motion.axis[0].maxSoftLimit)
00886         scratch_string[3] = '*';
00887       if (emcStatus->motion.axis[0].maxHardLimit)
00888         scratch_string[4] = '*';
00889       mvwaddstr(window, 10, 27, scratch_string);
00890 
00891       strcpy(scratch_string, "--Y--");
00892       if (emcStatus->motion.axis[1].minHardLimit)
00893         scratch_string[0] = '*';
00894       if (emcStatus->motion.axis[1].minSoftLimit)
00895         scratch_string[1] = '*';
00896       if (emcStatus->motion.axis[1].maxSoftLimit)
00897         scratch_string[3] = '*';
00898       if (emcStatus->motion.axis[1].maxHardLimit)
00899         scratch_string[4] = '*';
00900       mvwaddstr(window, 10, 47, scratch_string);
00901 
00902       strcpy(scratch_string, "--Z--");
00903       if (emcStatus->motion.axis[2].minHardLimit)
00904         scratch_string[0] = '*';
00905       if (emcStatus->motion.axis[2].minSoftLimit)
00906         scratch_string[1] = '*';
00907       if (emcStatus->motion.axis[2].maxSoftLimit)
00908         scratch_string[3] = '*';
00909       if (emcStatus->motion.axis[2].maxHardLimit)
00910         scratch_string[4] = '*';
00911       mvwaddstr(window, 10, 67, scratch_string);
00912 
00913       if (coords == COORD_ABSOLUTE)
00914         {
00915           if (posDisplay == POS_DISPLAY_CMD)
00916             {
00917               mvwaddstr(window, 11, 1, "Absolute Cmd Pos:");
00918             }
00919           else
00920             {
00921               mvwaddstr(window, 11, 1, "Absolute Act Pos:");
00922             }
00923           mvwaddstr(window, 12, 0, line_blank);
00924         }
00925       else
00926         {
00927           coords = COORD_RELATIVE;
00928           if (posDisplay == POS_DISPLAY_CMD)
00929             {
00930               mvwaddstr(window, 11, 1, "Relative Cmd Pos:");
00931             }
00932           else
00933             {
00934               mvwaddstr(window, 11, 1, "Relative Act Pos:");
00935             }
00936         }
00937 
00938       mvwaddstr(window, 14, 0, line_blank);
00939       mvwaddstr(window, 15, 0, line_blank);
00940       mvwaddstr(window, 16, 0, line_blank);
00941       mvwaddstr(window, 17, 0, line_blank);
00942       mvwaddstr(window, 18, 0, line_blank);
00943       mvwaddstr(window, 19, 0, line_blank);
00944       if (emcStatus->task.mode == EMC_TASK_MODE_AUTO)
00945         {
00946           mvwaddstr(window, 14, 1, "Program:");
00947           mvwaddstr(window, 15, 1, "Line:");
00948           mvwaddstr(window, 16, 1, "Command:");
00949           mvwaddstr(window, 17, 1, "Interpreter:");
00950           mvwaddstr(window, 18, 1, "Modal G Codes:");
00951           mvwaddstr(window, 19, 1, "Modal M Codes:");
00952         }
00953       else if (emcStatus->task.mode == EMC_TASK_MODE_MDI)
00954         {
00955           mvwaddstr(window, 16, 1, "Command:");
00956           mvwaddstr(window, 17, 1, "Interpreter:");
00957           mvwaddstr(window, 18, 1, "Modal G Codes:");
00958           mvwaddstr(window, 19, 1, "Modal M Codes:");
00959         }
00960 
00961       // end of labels
00962 
00963       // fill the status strings in
00964 
00965       switch(emcStatus->task.state)
00966         {
00967         case EMC_TASK_STATE_OFF:
00968           sprintf(state_string, "       OFF        ");
00969           break;
00970         case EMC_TASK_STATE_ON:
00971           sprintf(state_string, "       ON         ");
00972           break;
00973         case EMC_TASK_STATE_ESTOP:
00974           sprintf(state_string, "      ESTOP       ");
00975           break;
00976         case EMC_TASK_STATE_ESTOP_RESET:
00977           sprintf(state_string, "   ESTOP RESET    ");
00978           break;
00979         default:
00980           sprintf(state_string, "        ?         ");
00981           break;
00982         }
00983 
00984       switch(emcStatus->task.mode)
00985         {
00986         case EMC_TASK_MODE_MANUAL:
00987           sprintf(mode_string, "      MANUAL      ");
00988           break;
00989         case EMC_TASK_MODE_AUTO:
00990           sprintf(mode_string, "       AUTO       ");
00991           break;
00992         case EMC_TASK_MODE_MDI:
00993           sprintf(mode_string, "       MDI        ");
00994           break;
00995         default:
00996           sprintf(mode_string, "        ?         ");
00997           break;
00998         }
00999 
01000       if (emcStatus->io.spindle.increasing > 0)
01001         sprintf(spindle_string, " SPINDLE INCREASE ");
01002       else if (emcStatus->io.spindle.increasing < 0)
01003         sprintf(spindle_string, " SPINDLE DECREASE ");
01004       else if (emcStatus->io.spindle.direction > 0)
01005         sprintf(spindle_string, " SPINDLE FORWARD  ");
01006       else if (emcStatus->io.spindle.direction < 0)
01007         sprintf(spindle_string, " SPINDLE REVERSE  ");
01008       else
01009         sprintf(spindle_string, " SPINDLE STOPPED  ");
01010 
01011       if (emcStatus->io.spindle.brake)
01012         sprintf(brake_string,   "    BRAKE ON      ");
01013       else
01014         sprintf(brake_string,   "    BRAKE OFF     ");
01015 
01016       if (emcStatus->io.coolant.mist)
01017         sprintf(mist_string,    "    MIST ON       ");
01018       else
01019         sprintf(mist_string,    "    MIST OFF      ");
01020 
01021       if (emcStatus->io.coolant.flood)
01022         sprintf(flood_string,   "    FLOOD ON      ");
01023       else
01024         sprintf(flood_string,   "    FLOOD OFF     ");
01025 
01026       if (emcStatus->io.lube.on)
01027         sprintf(lube_on_string,    "     LUBE ON      ");
01028       else
01029         sprintf(lube_on_string,    "     LUBE OFF     ");
01030 
01031       if (! emcStatus->io.lube.level)
01032         sprintf(lube_level_string,    "     LUBE OK      ");
01033       else
01034         sprintf(lube_level_string,    "     LUBE LOW     ");
01035 
01036       sprintf(home_string, "    --- HOMED     ");
01037       if (emcStatus->motion.axis[0].homed)
01038         {
01039           home_string[4] = 'X';
01040         }
01041       if (emcStatus->motion.axis[1].homed)
01042         {
01043           home_string[5] = 'Y';
01044         }
01045       if (emcStatus->motion.axis[2].homed)
01046         {
01047           home_string[6] = 'Z';
01048         }
01049 
01050       if (coords == COORD_ABSOLUTE)
01051         {
01052           if (posDisplay == POS_DISPLAY_ACT)
01053             {
01054               sprintf(pos_string, "%13.4f  %18.4f  %18.4f",
01055                       emcStatus->motion.traj.actualPosition.tran.x,
01056                       emcStatus->motion.traj.actualPosition.tran.y,
01057                       emcStatus->motion.traj.actualPosition.tran.z);
01058             }
01059           else
01060             {
01061               sprintf(pos_string, "%13.4f  %18.4f  %18.4f",
01062                       emcStatus->motion.traj.position.tran.x,
01063                       emcStatus->motion.traj.position.tran.y,
01064                       emcStatus->motion.traj.position.tran.z);
01065             }
01066         }
01067       else
01068         {
01069           coords = COORD_RELATIVE;
01070           if (posDisplay == POS_DISPLAY_ACT)
01071             {
01072               sprintf(pos_string, "%13.4f  %18.4f  %18.4f",
01073                       emcStatus->motion.traj.actualPosition.tran.x -
01074                       emcStatus->task.origin.tran.x,
01075                       emcStatus->motion.traj.actualPosition.tran.y -
01076                       emcStatus->task.origin.tran.y,
01077                       emcStatus->motion.traj.actualPosition.tran.z -
01078                       emcStatus->task.origin.tran.z -
01079                       emcStatus->task.toolOffset.tran.z);
01080             }
01081           else
01082             {
01083               sprintf(pos_string, "%13.4f  %18.4f  %18.4f",
01084                       emcStatus->motion.traj.position.tran.x -
01085                       emcStatus->task.origin.tran.x,
01086                       emcStatus->motion.traj.position.tran.y -
01087                       emcStatus->task.origin.tran.y,
01088                       emcStatus->motion.traj.position.tran.z -
01089                       emcStatus->task.origin.tran.z -
01090                       emcStatus->task.toolOffset.tran.z);
01091             }
01092         }
01093 
01094       sprintf(origin_string, "%13.4f  %18.4f  %18.4f",
01095               emcStatus->task.origin.tran.x,
01096               emcStatus->task.origin.tran.y,
01097               emcStatus->task.origin.tran.z);
01098 
01099       sprintf(speed_string, "%10.1f", jogSpeed);
01100       if (jogMode == JOG_INCREMENTAL)
01101         {
01102           sprintf(incr_string,  "%10.4f", jogIncrement);
01103         }
01104       else
01105         {
01106           sprintf(incr_string, "continuous");
01107         }
01108 
01109       if (! programOpened)
01110         {
01111           // print the last one opened, since we'll send this by default
01112           strcpy(prog_string, programFile);
01113         }
01114       else
01115         {
01116           // print the one the controller knows about
01117           strcpy(prog_string, emcStatus->task.file);
01118         }
01119 
01120       if (emcStatus->task.currentLine > 0)
01121         {
01122           if (emcStatus->task.motionLine > 0 &&
01123               emcStatus->task.motionLine < emcStatus->task.currentLine)
01124             {
01125               programActiveLine = emcStatus->task.motionLine;
01126             }
01127           else
01128             {
01129               programActiveLine = emcStatus->task.currentLine;
01130             }
01131           sprintf(line_string, "%d", programActiveLine);
01132           if (programFp != 0)
01133             {
01134               if (programFpLine > programActiveLine)
01135                 {
01136                   rewind(programFp);
01137                   programFpLine = 0;
01138                   programLineText[0] = 0;
01139                 }
01140 
01141               // fast forward over past lines
01142               while (programFpLine < programActiveLine)
01143                 {
01144                   fgets(programLineText, EMC_TASK_COMMAND_LEN, programFp);
01145                   programFpLine++;
01146                 }
01147 
01148               // now we have the current line
01149               // knock off CR, LF
01150               len = strlen(programLineText) - 1;
01151               while (len >= 0)
01152                 {
01153                   if (isspace(programLineText[len]))
01154                     {
01155                       programLineText[len] = 0;
01156                       len--;
01157                     }
01158                   else
01159                     {
01160                       break;
01161                     }
01162                 }
01163             }
01164           else
01165             {
01166               programLineText[0] = 0;
01167             }
01168         }
01169       else
01170         {
01171           programActiveLine = 0;
01172           programLineText[0] = 0;
01173           line_string[0] = 0;
01174         }
01175 
01176       switch (emcStatus->task.interpState)
01177         {
01178         case EMC_TASK_INTERP_IDLE:
01179           sprintf(interp_string, "%s", "IDLE    ");
01180           break;
01181         case EMC_TASK_INTERP_READING:
01182           sprintf(interp_string, "%s", "RUNNING ");
01183           break;
01184         case EMC_TASK_INTERP_PAUSED:
01185           sprintf(interp_string, "%s", "PAUSED  ");
01186           break;
01187         case EMC_TASK_INTERP_WAITING:
01188           sprintf(interp_string, "%s", "RUNNING ");
01189           break;
01190         default:
01191           sprintf(interp_string, "%s", "?       ");
01192           break;
01193         }
01194 
01195       // fill in the active G codes
01196       active_g_codes_string[0] = 0;
01197       for (t = 1; t < EMC_TASK_ACTIVE_G_CODES; t++)
01198         {
01199           code = emcStatus->task.activeGCodes[t];
01200           if (code == -1)
01201             continue;
01202           if (code % 10)
01203             sprintf(scratch_string, "G%.1f ", (double) code / 10.0);
01204           else
01205             sprintf(scratch_string, "G%d ", code / 10);
01206           strcat(active_g_codes_string, scratch_string);
01207         }
01208 
01209       // fill in the active M codes, settings too
01210       active_m_codes_string[0] = 0;
01211       for (t = 1; t < EMC_TASK_ACTIVE_M_CODES; t++)
01212         {
01213           code = emcStatus->task.activeMCodes[t];
01214           if (code == -1)
01215             continue;
01216           sprintf(scratch_string, "M%d ", code);
01217           strcat(active_m_codes_string, scratch_string);
01218         }
01219       sprintf(scratch_string, "F%.0f ", emcStatus->task.activeSettings[1]);
01220       strcat(active_m_codes_string, scratch_string);
01221       sprintf(scratch_string, "S%.0f ", emcStatus->task.activeSettings[2]);
01222       strcat(active_m_codes_string, scratch_string);
01223 
01224       // fill the screen in
01225 
01226       override = (int) (emcStatus->motion.traj.scale * 100.0 + 0.5);
01227       sprintf(scratch_string, "%4d%%", override);
01228       if (override < 100)
01229         wattrset(window, A_BOLD);
01230       else
01231         wattrset(window, A_UNDERLINE);
01232       mvwaddstr(window, 6, 14, scratch_string);
01233 
01234       sprintf(scratch_string, "%8d", emcStatus->io.tool.toolInSpindle);
01235       wattrset(window, A_UNDERLINE);
01236       mvwaddstr(window, 7, 11, scratch_string);
01237 
01238       sprintf(scratch_string, "%8.4f", emcStatus->task.toolOffset.tran.z);
01239       wattrset(window, A_UNDERLINE);
01240       mvwaddstr(window, 8, 11, scratch_string);
01241 
01242       wattrset(window, A_REVERSE);
01243 
01244       mvwaddstr(window, 5, 1, state_string);
01245       mvwaddstr(window, 5, 21, mode_string);
01246       mvwaddstr(window, 6, 21, lube_on_string);
01247       mvwaddstr(window, 7, 21, lube_level_string);
01248       mvwaddstr(window, 5, 41, spindle_string);
01249       mvwaddstr(window, 6, 41, brake_string);
01250       mvwaddstr(window, 7, 41, mist_string);
01251       mvwaddstr(window, 8, 41, flood_string);
01252       mvwaddstr(window, 5, 61, home_string);
01253       mvwaddstr(window, 6, 61, axisString(axisSelected));
01254 
01255       wattrset(window, A_UNDERLINE);
01256 
01257       mvwaddstr(window, 11, 21, pos_string);
01258 
01259       if (coords == COORD_RELATIVE)
01260         {
01261           wattrset(window, 0);
01262           mvwaddstr(window, 12, 21, origin_string);
01263         }
01264 
01265       wattrset(window, A_UNDERLINE);
01266 
01267       mvwaddstr(window, 7, 69, speed_string);
01268       mvwaddstr(window, 8, 69, incr_string);
01269 
01270       if (emcStatus->task.mode == EMC_TASK_MODE_AUTO)
01271         {
01272           mvwaddstr(window, 14, 21, prog_string);
01273           mvwaddstr(window, 15, 21, line_string);
01274           if (emcStatus->task.interpState == EMC_TASK_INTERP_PAUSED)
01275             wattrset(window, A_BOLD);
01276           mvwaddstr(window, 16, 21, programLineText);
01277           mvwaddstr(window, 17, 21, interp_string);
01278           wattrset(window, A_UNDERLINE);
01279           mvwaddstr(window, 18, 21, active_g_codes_string);
01280           mvwaddstr(window, 19, 21, active_m_codes_string);
01281         }
01282       else if (emcStatus->task.mode == EMC_TASK_MODE_MDI)
01283         {
01284           if (emcStatus->task.interpState == EMC_TASK_INTERP_PAUSED)
01285             wattrset(window, A_BOLD);
01286           mvwaddstr(window, 16, 21, emcStatus->task.command);
01287           mvwaddstr(window, 17, 21, interp_string);
01288           wattrset(window, A_UNDERLINE);
01289           mvwaddstr(window, 18, 21, active_g_codes_string);
01290           mvwaddstr(window, 19, 21, active_m_codes_string);
01291         }
01292 
01293       if (error_string[0] != 0)
01294         {
01295           printError(error_string);
01296         }
01297 
01298       wattrset(window, A_REVERSE);
01299       mvwaddstr(window, wmaxy - 1, wbegx, bottom_string);
01300       wattrset(window, 0);
01301 
01302       // restore cursor position
01303       wmove(window, savey, savex);
01304       wrefresh(window);
01305     }
01306 }
01307 
01308 static int catchErrors = 1;
01309 
01310 static int updateStatus()
01311 {
01312   NMLTYPE type;
01313 
01314   if (0 == emcStatus ||
01315       0 == emcStatusBuffer ||
01316       ! emcStatusBuffer->valid())
01317     {
01318       return -1;
01319     }
01320 
01321   if (catchErrors)
01322     {
01323       if (0 == emcErrorBuffer ||
01324           ! emcErrorBuffer->valid())
01325         {
01326           return -1;
01327         }
01328     }
01329 
01330   switch (type = emcStatusBuffer->peek())
01331     {
01332     case -1:
01333       // error on CMS channel
01334       return -1;
01335       break;
01336 
01337     case 0:                     // no new data
01338     case EMC_STAT_TYPE: // new data
01339       // new data
01340       break;
01341 
01342     default:
01343       return -1;
01344       break;
01345     }
01346 
01347   if (catchErrors)
01348     {
01349       switch (type = emcErrorBuffer->read())
01350         {
01351         case -1:
01352           // error reading channel
01353           break;
01354 
01355         case 0:
01356           // nothing new
01357           error_string[0] = 0;
01358           break;
01359 
01360         case EMC_OPERATOR_ERROR_TYPE:
01361           strncpy(error_string,
01362                   ((EMC_OPERATOR_ERROR *) (emcErrorBuffer->get_address()))->error,
01363                   EMC_OPERATOR_ERROR_LEN - 1);
01364           error_string[EMC_OPERATOR_ERROR_LEN - 1] = 0;
01365           break;
01366 
01367         case EMC_OPERATOR_TEXT_TYPE:
01368           strncpy(error_string,
01369                   ((EMC_OPERATOR_TEXT *) (emcErrorBuffer->get_address()))->text,
01370                   EMC_OPERATOR_ERROR_LEN - 1);
01371           error_string[EMC_OPERATOR_ERROR_LEN - 1] = 0;
01372           break;
01373 
01374         case EMC_OPERATOR_DISPLAY_TYPE:
01375           strncpy(error_string,
01376                   ((EMC_OPERATOR_DISPLAY *) (emcErrorBuffer->get_address()))->display,
01377                   EMC_OPERATOR_ERROR_LEN - 1);
01378           error_string[EMC_OPERATOR_ERROR_LEN - 1] = 0;
01379           break;
01380 
01381 
01382         case NML_ERROR_TYPE:
01383           strncpy(error_string,
01384                   ((NML_ERROR *) (emcErrorBuffer->get_address()))->error,
01385                   NML_ERROR_LEN - 1);
01386           error_string[NML_ERROR_LEN - 1] = 0;
01387           break;
01388 
01389         case NML_TEXT_TYPE:
01390           strncpy(error_string,
01391                   ((NML_TEXT *) (emcErrorBuffer->get_address()))->text,
01392                   NML_ERROR_LEN - 1);
01393           error_string[NML_ERROR_LEN - 1] = 0;
01394           break;
01395 
01396         case NML_DISPLAY_TYPE:
01397           strncpy(error_string,
01398                   ((NML_DISPLAY *) (emcErrorBuffer->get_address()))->display,
01399                   NML_ERROR_LEN - 1);
01400           error_string[NML_ERROR_LEN - 1] = 0;
01401           break;
01402 
01403         default:
01404           strcpy(error_string, "unrecognized error");
01405           break;
01406         }
01407     }
01408 
01409   return 0;
01410 }
01411 
01412 /*
01413   waits until the EMC reports that it's got the command with the
01414   indicated serial_number. Sleeps between queries.
01415 */
01416 
01417 #define EMC_COMMAND_TIMEOUT 1.0 // how long to wait until timeout
01418 #define EMC_COMMAND_DELAY   0.1 // how long to sleep between checks
01419 
01420 static int emcCommandWait(int serial_number)
01421 {
01422   double start = etime();
01423 
01424   while (etime() - start < EMC_COMMAND_TIMEOUT)
01425     {
01426       updateStatus();
01427 
01428       if (emcStatus->echo_serial_number == serial_number)
01429         {
01430           return 0;
01431         }
01432 
01433       esleep(EMC_COMMAND_DELAY);
01434     }
01435 
01436   printError("timeout sending command");
01437 
01438   return -1;
01439 }
01440 
01441 /*
01442   startTimer starts the timer to generate SIGALRM events, or stops the timer
01443   if 'us' is 0. Enable a signal handler for SIGALRM before you call this.
01444 */
01445 void startTimer(int us)
01446 {
01447   struct itimerval value;
01448 
01449   value.it_interval.tv_sec = 0;
01450   value.it_interval.tv_usec = us;
01451   value.it_value.tv_sec = 0;
01452   value.it_value.tv_usec = us;
01453 
01454   setitimer(ITIMER_REAL, &value, 0);
01455 }
01456 
01457 /*
01458   alarmHandler is attached to SIGALRM, and handles the reading of NML
01459   status, the update of the status window, and key-up simulation and
01460   handling
01461 */
01462 static void alarmHandler(int sig)
01463 {
01464   // mask out this signal for now
01465   signal(SIGALRM, SIG_IGN);
01466 
01467   // read NML status
01468   updateStatus();
01469 
01470   // only print if main is not printing, so we don't clobber in the middle
01471   if (! critFlag)
01472     {
01473       printStatus();
01474     }
01475 
01476   // simulate key-up event, as per comment below
01477   keyup_count -= usecs;
01478   if (keyup_count < 0)
01479     {
01480       keyup_count = 0;
01481       oldch = 0;
01482     }
01483 
01484   /*
01485     Key-up events are simulated as follows: each time a key is received,
01486     keyup_count is loaded. If it's a new key, FIRST_KEYUP_DELAY is
01487     loaded. If it's the same as the last key, NEXT_KEYUP_DELAY is loaded.
01488     This is to handle the different delay between the first and subsequent
01489     repeats.
01490 
01491     Each time through this handler, keyup_count is decremented. If it
01492     reaches 0, it means no key has been pressed before the delay expires,
01493     and we see this as a key-up event.
01494 
01495     If you have code that needs to respond to a key-up event, set a flag
01496     when you do your key-down stuff, and put the key-up code in here,
01497     like this:
01498 
01499     if (myFlag && keyup_count == 0)
01500       {
01501         // do stuff for key up here
01502 
01503         // and clear your flag
01504         myFlag = 0;
01505       }
01506    */
01507 
01508   // key up for jogs
01509   if (axisJogging != AXIS_NONE && keyup_count == 0)
01510     {
01511       emc_axis_abort_msg.axis = axisIndex(axisJogging);
01512       emc_axis_abort_msg.serial_number = ++emcCommandSerialNumber;
01513       emcCommandBuffer->write(emc_axis_abort_msg);
01514       emcCommandWait(emcCommandSerialNumber);
01515       axisJogging = AXIS_NONE;
01516     }
01517 
01518   // key up for spindle speed changes
01519   if (spindleChanging && keyup_count == 0)
01520     {
01521       emc_spindle_constant_msg.serial_number = ++emcCommandSerialNumber;
01522       emcCommandBuffer->write(emc_spindle_constant_msg);
01523       emcCommandWait(emcCommandSerialNumber);
01524       spindleChanging = 0;
01525     }
01526 
01527   // reenable this signal
01528   signal(SIGALRM, alarmHandler);
01529 
01530   return;
01531 }
01532 
01533 static int done = 0;
01534 static void quit(int sig)
01535 {
01536   // disable timer
01537   startTimer(0);
01538 
01539   // clean up curses windows
01540   delwin(progwin);
01541   progwin = 0;
01542   delwin(logwin);
01543   logwin = 0;
01544   delwin(toolwin);
01545   toolwin = 0;
01546   delwin(diagwin);
01547   diagwin = 0;
01548   delwin(helpwin);
01549   helpwin = 0;
01550   endwin();
01551 
01552   // clean up NML buffers
01553 
01554   if (emcErrorBuffer != 0)
01555     {
01556       delete emcErrorBuffer;
01557       emcErrorBuffer = 0;
01558     }
01559 
01560   if (emcStatusBuffer != 0)
01561     {
01562       delete emcStatusBuffer;
01563       emcStatusBuffer = 0;
01564       emcStatus = 0;
01565     }
01566 
01567   if (emcCommandBuffer != 0)
01568     {
01569       delete emcCommandBuffer;
01570       emcCommandBuffer = 0;
01571     }
01572 
01573   // close program file
01574   if (programFp != 0)
01575     {
01576       fclose(programFp);
01577       programFp = 0;
01578     }
01579 
01580   // close error log file
01581   if (NULL != errorFp)
01582     {
01583       fclose(errorFp);
01584       errorFp = NULL;
01585     }
01586 
01587   // reset signal handlers to default
01588   signal(SIGALRM, SIG_DFL);
01589   signal(SIGINT, SIG_DFL);
01590 
01591   exit(0);
01592 }
01593 
01594 static int emcTaskNmlGet()
01595 {
01596   int retval = 0;
01597 
01598   // try to connect to EMC cmd
01599   if (emcCommandBuffer == 0)
01600     {
01601       emcCommandBuffer = new RCS_CMD_CHANNEL(emcFormat, "emcCommand", "keystick", EMC_NMLFILE);
01602       if (! emcCommandBuffer->valid())
01603         {
01604           rcs_print_error("emcCommand buffer not available\n");
01605           delete emcCommandBuffer;
01606           emcCommandBuffer = 0;
01607           retval = -1;
01608         }
01609     }
01610 
01611   // try to connect to EMC status
01612   if (emcStatusBuffer == 0)
01613     {
01614       emcStatusBuffer = new RCS_STAT_CHANNEL(emcFormat, "emcStatus", "keystick", EMC_NMLFILE);
01615       if (! emcStatusBuffer->valid() ||
01616           EMC_STAT_TYPE != emcStatusBuffer->peek())
01617         {
01618           rcs_print_error("emcStatus buffer not available\n");
01619           delete emcStatusBuffer;
01620           emcStatusBuffer = 0;
01621           emcStatus = 0;
01622           retval = -1;
01623         }
01624       else
01625         {
01626           emcStatus = (EMC_STAT *) emcStatusBuffer->get_address();
01627         }
01628     }
01629 
01630   return retval;
01631 }
01632 
01633 static int emcErrorNmlGet()
01634 {
01635   int retval = 0;
01636 
01637   if (emcErrorBuffer == 0)
01638     {
01639       emcErrorBuffer = new NML(nmlErrorFormat, "emcError", "keystick", EMC_NMLFILE);
01640       if (! emcErrorBuffer->valid())
01641         {
01642           rcs_print_error("emcError buffer not available\n");
01643           delete emcErrorBuffer;
01644           emcErrorBuffer = 0;
01645           retval = -1;
01646         }
01647     }
01648 
01649   return retval;
01650 }
01651 
01652 // string for ini file version num
01653 static char version_string[INIFILE_MAX_LINELEN] = "";
01654 
01655 // destructively converts string to its uppercase counterpart
01656 static char *upcase(char *string)
01657 {
01658   char *ptr = string;
01659   int jogPol;
01660 
01661   while (*ptr != 0)
01662     {
01663       *ptr = toupper(*ptr);
01664       ptr++;
01665     }
01666 
01667   return string;
01668 }
01669 
01670 static int iniLoad(const char *filename)
01671 {
01672   INIFILE inifile;
01673   const char *inistring;
01674   char machine[INIFILE_MAX_LINELEN] = "";
01675   char version[INIFILE_MAX_LINELEN] = "";
01676   char displayString[INIFILE_MAX_LINELEN] = "";
01677   int jogPol;
01678 
01679   // open it
01680   if (-1 == inifile.open(filename))
01681     {
01682       return -1;
01683     }
01684 
01685   if (NULL != (inistring = inifile.find("MACHINE", "EMC")))
01686     {
01687       strcpy(machine, inistring);
01688 
01689       if (NULL != (inistring = inifile.find("VERSION", "EMC")))
01690         {
01691           sscanf(inistring, "$Revision: %s", version);
01692 
01693           sprintf(version_string, "%s EMC Version %s", machine, version);
01694         }
01695     }
01696 
01697   if (NULL != (inistring = inifile.find("MAX_VELOCITY", "TRAJ")))
01698     {
01699       if (1 != sscanf(inistring, "%lf", &TRAJ_MAX_VELOCITY))
01700         {
01701           TRAJ_MAX_VELOCITY = DEFAULT_TRAJ_MAX_VELOCITY;
01702         }
01703     }
01704   else
01705     {
01706       TRAJ_MAX_VELOCITY = DEFAULT_TRAJ_MAX_VELOCITY;
01707     }
01708 
01709   if (NULL != (inistring = inifile.find("PROGRAM_PREFIX", "TASK")))
01710     {
01711       if (1 != sscanf(inistring, "%s", programPrefix))
01712         {
01713           programPrefix[0] = 0;
01714         }
01715     }
01716   else
01717     {
01718       programPrefix[0] = 0;
01719     }
01720 
01721   if (NULL != (inistring = inifile.find("POSITION_OFFSET", "DISPLAY")))
01722     {
01723       if (1 == sscanf(inistring, "%s", displayString))
01724         {
01725           upcase(displayString);
01726           if (! strcmp(displayString, "ABSOLUTE"))
01727             {
01728               coords = COORD_ABSOLUTE;
01729             }
01730           else if (! strcmp(displayString, "RELATIVE"))
01731             {
01732               coords = COORD_RELATIVE;
01733             }
01734           else
01735             {
01736               // error-- invalid value
01737               // ignore
01738             }
01739         }
01740       else
01741         {
01742           // error-- no value provided
01743           // ignore
01744         }
01745     }
01746   else
01747     {
01748       // no line at all
01749       // ignore
01750     }
01751 
01752   if (NULL != (inistring = inifile.find("POSITION_FEEDBACK", "DISPLAY")))
01753     {
01754       if (1 == sscanf(inistring, "%s", displayString))
01755         {
01756           upcase(displayString);
01757           if (! strcmp(displayString, "ACTUAL"))
01758             {
01759               posDisplay = POS_DISPLAY_ACT;
01760             }
01761           else if (! strcmp(displayString, "COMMANDED"))
01762             {
01763               posDisplay = POS_DISPLAY_CMD;
01764             }
01765           else
01766             {
01767               // error-- invalid value
01768               // ignore
01769             }
01770         }
01771       else
01772         {
01773           // error-- no value provided
01774           // ignore
01775         }
01776     }
01777   else
01778     {
01779       // no line at all
01780       // ignore
01781     }
01782 
01783   xJogPol = 1;                  // set to default
01784   if (NULL != (inistring = inifile.find("JOGGING_POLARITY", "AXIS_0")) &&
01785       1 == sscanf(inistring, "%d", &jogPol) &&
01786       jogPol == 0)
01787     {
01788       // it read as 0, so override default
01789       xJogPol = 0;
01790     }
01791 
01792   yJogPol = 1;                  // set to default
01793   if (NULL != (inistring = inifile.find("JOGGING_POLARITY", "AXIS_1")) &&
01794       1 == sscanf(inistring, "%d", &jogPol) &&
01795       jogPol == 0)
01796     {
01797       // it read as 0, so override default
01798       yJogPol = 0;
01799     }
01800 
01801   zJogPol = 1;                  // set to default
01802   if (NULL != (inistring = inifile.find("JOGGING_POLARITY", "AXIS_2")) &&
01803       1 == sscanf(inistring, "%d", &jogPol) &&
01804       jogPol == 0)
01805     {
01806       // it read as 0, so override default
01807       zJogPol = 0;
01808     }
01809 
01810   // close it
01811   inifile.close();
01812 
01813   return 0;;
01814 }
01815 
01816 int main(int argc, char *argv[])
01817 {
01818   int dump = 0;
01819   struct winsize size;
01820   int curx, cury;
01821   int t;
01822   int typing = 0;
01823 #define TYPEBUFFERSIZE LINELEN
01824   char typebuffer[TYPEBUFFERSIZE];
01825   char lastmdi[TYPEBUFFERSIZE] = "";
01826   int typeindex = 0;
01827   enum {IACT_NONE = 1, IACT_OPEN, IACT_MDI, IACT_LOAD_TOOL, IACT_OPEN_LOG,
01828         IACT_END} interactive = IACT_NONE;
01829   char keystick[] = "keystick";
01830   int charHandled;
01831 
01832   // process command line args, indexing argv[] from [1]
01833   for (t = 1; t < argc; t++)
01834     {
01835       // try -dump
01836       if (!strcmp(argv[t], "-dump"))
01837         {
01838           dump = 1;
01839           t++;          // step over nmlfile
01840           continue;
01841         }
01842 
01843       // try -nml
01844       if (!strcmp(argv[t], "-nml"))
01845         {
01846           if (t == argc - 1)    // if last, can't read past it
01847             {
01848               printf("syntax: -nml <nmlfile>\n");
01849               exit(1);
01850             }
01851           else
01852             {
01853               strcpy(EMC_NMLFILE, argv[t+1]);
01854               t++;              // step over nmlfile
01855               continue;
01856             }
01857         }
01858 
01859       // try -ini
01860       if (!strcmp(argv[t], "-ini"))
01861         {
01862           if (t == argc - 1)
01863             {
01864               printf("syntax: -ini <inifile\n");
01865               exit(1);
01866             }
01867           else
01868             {
01869               strcpy(EMC_INIFILE, argv[t+1]);
01870               t++;              // step over inifile
01871               continue;
01872             }
01873         }
01874 
01875       // try -noerror
01876       if (!strcmp(argv[t], "-noerror"))
01877         {
01878           catchErrors = 0;
01879           continue;
01880         }
01881 
01882       // try -usecs for cycle time in microseconds
01883       if (!strcmp(argv[t], "-usecs"))
01884         {
01885           if (t == argc - 1 ||
01886               1 != sscanf(argv[t + 1], "%d", &usecs) ||
01887               usecs <= 0 ||
01888               usecs >= 1000000)
01889             {
01890               printf("syntax: -usecs <1..999999 microsecond polling period>\n");
01891               exit(1);
01892             }
01893           else
01894             {
01895               t++;
01896               continue;
01897             }
01898         }
01899 
01900       // try -dur for delay until repeat
01901       if (!strcmp(argv[t], "-dur"))
01902         {
01903           if (t == argc - 1 ||
01904               1 != sscanf(argv[t + 1], "%d", &FIRST_KEYUP_DELAY) ||
01905               FIRST_KEYUP_DELAY < 0)
01906             {
01907               printf("syntax: -dur <usecs delay until first repeat>\n");
01908               exit(1);
01909             }
01910           else
01911             {
01912               t++;
01913               continue;
01914             }
01915         }
01916 
01917       // try -dbr for delay between repeats
01918       if (!strcmp(argv[t], "-dbr"))
01919         {
01920           if (t == argc - 1 ||
01921               1 != sscanf(argv[t + 1], "%d", &NEXT_KEYUP_DELAY) ||
01922               NEXT_KEYUP_DELAY < 0)
01923             {
01924               printf("syntax: -dbr <usecs delay between repeats>\n");
01925               exit(1);
01926             }
01927           else
01928             {
01929               t++;
01930               continue;
01931             }
01932         }
01933 
01934     }
01935 
01936   // read INI file
01937   iniLoad(EMC_INIFILE);
01938 
01939   // trap SIGINT
01940   signal(SIGINT, quit);
01941 
01942   // set up handler for SIGALRM to handle periodic timer events
01943   signal(SIGALRM, alarmHandler);
01944 
01945   // open error file for logging
01946   if (NULL == (errorFp = fopen(ERROR_FILE, "w")))
01947     {
01948       // ignore; null errorFp will prevent attempts to log
01949     }
01950 
01951   // blank out the annoying RCS version message
01952   rcs_version_printed = 1;
01953 
01954   // init NML
01955   if (! dump)
01956     {
01957       if (0 != emcTaskNmlGet())
01958         {
01959           exit(1);
01960         }
01961       if (0 != emcErrorNmlGet())
01962         {
01963           exit(1);
01964         }
01965     }
01966 
01967   // set up curses
01968   initscr();
01969   cbreak();
01970   noecho();
01971   nonl();
01972   intrflush(stdscr, FALSE);
01973   keypad(stdscr, TRUE);
01974   helpwin = newwin(0, 0, 0, 0);
01975   diagwin = newwin(0, 0, 0, 0);
01976   toolwin = newwin(0, 0, 0, 0);
01977   logwin = newwin(0, 0, 0, 0);
01978   progwin = newwin(0, 0, 0, 0);
01979   window = stdscr;
01980 
01981   // fill in strings
01982 
01983   for (t = 0; t < LINELEN; t++)
01984     {
01985       line_blank[t] = ' ';
01986     }
01987   line_blank[LINELEN] = 0;
01988 
01989   for (t = 0; t < LINELEN; t++)
01990     {
01991       bottom_string[t] = '-';
01992     }
01993   bottom_string[LINELEN] = 0;
01994   t = (LINELEN - strlen(version_string)) / 2;
01995   if (t >= 0)
01996     {
01997       memcpy(&bottom_string[t], version_string, strlen(version_string));
01998     }
01999 
02000   // get screen width and height
02001   wbegy = 0;
02002   wbegx = 0;
02003   if (ioctl(STDIN_FILENO, TIOCGWINSZ, &size) < 0)
02004     {
02005       // use 80x24 as default
02006       wmaxy = 23;
02007       wmaxx = 79;
02008     }
02009   else
02010     {
02011       wmaxy = size.ws_row - 1;
02012       wmaxx = size.ws_col - 1;
02013     }
02014 
02015   // and set them here
02016   cury = wmaxy;
02017   curx = wbegx;
02018   wmove(window, cury, curx);
02019   wrefresh(window);
02020 
02021   // set up interval timer
02022   if (!dump)
02023     {
02024       startTimer(usecs);
02025     }
02026 
02027   while (! done)
02028     {
02029       oldch = ch;
02030       ch = (chtype) getch();
02031       // check for ^C that may happen during blocking read
02032       if (done)
02033         {
02034           break;
02035         }
02036 
02037       if (dump)
02038         {
02039           mvwaddstr(window, wmaxy, wbegx, line_blank);
02040           sprintf(scratch_string, "%12o", (int) ch);
02041           mvwaddstr(window, wmaxy, wbegx, scratch_string);
02042           wmove(window, wmaxy, wbegx);
02043           wrefresh(window);
02044 
02045           if (ch == 'q')
02046             break;
02047           else
02048             continue;
02049         }
02050 
02051       if (ch != oldch)
02052         {
02053           keyup_count = FIRST_KEYUP_DELAY;
02054         }
02055       else
02056         {
02057           keyup_count = NEXT_KEYUP_DELAY;
02058         }
02059 
02060       // set up a first switch on ch, for those characters that
02061       // are to be looked at before the interactive typing string.
02062       // set flag signifying the char has been handled, which will
02063       // be reset in the default (not handled) case
02064       charHandled = 1;
02065       switch (ch)
02066         {
02067           /*
02068             To implement a "repeated key," whose actions are done
02069             during the first and every repeated key, do this:
02070 
02071             case MY_REPEATED_KEY:
02072             // do action
02073             // you need do nothing else
02074             break;
02075 
02076             To implement a "single key," whose actions are done
02077             once and not repeated if the key repeats, do this:
02078 
02079             case MY_SINGLE_KEY:
02080             if (oldch != ch)
02081             {
02082             // do action
02083             // you need do nothing else
02084             }
02085             break;
02086 
02087             The simulated key-up event and setting of oldch is done
02088             automatically elsewhere.
02089           */
02090 
02091         case ESC:               // task abort (abort everything)
02092           task_abort_msg.serial_number = ++emcCommandSerialNumber;
02093           emcCommandBuffer->write(task_abort_msg);
02094           emcCommandWait(emcCommandSerialNumber);
02095           break;
02096 
02097         case TAB:               // toggle highlight
02098           if (window == logwin)
02099             {
02100               // toggle log highlight
02101               if (logtab == LOG_TYPE)
02102                 logtab = LOG_SIZE;
02103               else if (logtab == LOG_SIZE)
02104                 logtab = LOG_SKIP;
02105               else if (logtab == LOG_SKIP &&
02106                        saveLogType == EMC_LOG_TYPE_AXIS_POS)
02107                 logtab = LOG_AXIS;
02108               else
02109                 logtab = LOG_TYPE;
02110             }
02111           else if (window == diagwin)
02112             {
02113               // toggle dianostics highlight
02114               if (diagtab == DIAG_USECS)
02115                 diagtab = DIAG_FIRST_KEYUP_DELAY;
02116               else if (diagtab == DIAG_FIRST_KEYUP_DELAY)
02117                 diagtab = DIAG_NEXT_KEYUP_DELAY;
02118               else
02119                 diagtab = DIAG_USECS;
02120             }
02121           break;
02122 
02123         case ALT('o'):          // open log
02124         case ALT('O'):
02125           if (oldch != ch)
02126             {
02127               typing = 1;
02128               typeindex = 0;
02129               interactive = IACT_OPEN_LOG;
02130 
02131               critFlag = 1;
02132               mvwaddstr(window, wmaxy, wbegx, line_blank);
02133               mvwaddstr(window, wmaxy, wbegx, "log file to open: ");
02134               wrefresh(window);
02135               critFlag = 0;
02136             }
02137           break;
02138 
02139         case ALT('p'):          // pause (or stop) log
02140         case ALT('P'):
02141           if (oldch != ch)
02142             {
02143               emc_log_stop_msg.serial_number = ++emcCommandSerialNumber;
02144               emcCommandBuffer->write(emc_log_stop_msg);
02145               emcCommandWait(emcCommandSerialNumber);
02146             }
02147           break;
02148 
02149         case ALT('s'):          // resume (or start) log
02150         case ALT('S'):
02151           if (oldch != ch)
02152             {
02153               // check for open log file first; if not, and old one saved,
02154               // open old one
02155               if (! emcStatus->logOpen)
02156                 {
02157                   if (saveLogFile[0] != 0)
02158                     {
02159                       strcpy(emc_log_open_msg.file, saveLogFile);
02160                       emc_log_open_msg.type = saveLogType;
02161                       emc_log_open_msg.size = saveLogSize;
02162                       emc_log_open_msg.skip = saveLogSkip;
02163                       emc_log_open_msg.which = saveLogAxis;
02164                       emc_log_open_msg.serial_number = ++emcCommandSerialNumber;
02165                       emcCommandBuffer->write(emc_log_open_msg);
02166                       emcCommandWait(emcCommandSerialNumber);
02167                     }
02168                   else
02169                     {
02170                       // log is not opened, and no name saved, so ignore
02171                       break;
02172                     }
02173                 }
02174 
02175               emc_log_start_msg.serial_number = ++emcCommandSerialNumber;
02176               emcCommandBuffer->write(emc_log_start_msg);
02177               emcCommandWait(emcCommandSerialNumber);
02178             }
02179           break;
02180 
02181         case ALT('f'):          // close (and save) log to file
02182         case ALT('F'):
02183           if (oldch != ch)
02184             {
02185               emc_log_close_msg.serial_number = ++emcCommandSerialNumber;
02186               emcCommandBuffer->write(emc_log_close_msg);
02187               emcCommandWait(emcCommandSerialNumber);
02188             }
02189           break;
02190 
02191         case CTL('P'):          // plot log file
02192           if (oldch != ch)
02193             {
02194               if (0 != plotLog(saveLogFile, saveLogType, saveLogAxis))
02195                 {
02196                   sprintf(scratch_string, "can't print log %s-- check log file manually", saveLogFile);
02197                   printError(scratch_string);
02198                 }
02199             }
02200           break;
02201 
02202         case CTL('L'):          // redraw current window
02203           clearWindow();
02204           printStatus();
02205           break;
02206 
02207         case KEY_F(1):          // toggle estop
02208           if (oldch != ch)
02209             {
02210               if (emcStatus->task.state == EMC_TASK_STATE_ESTOP)
02211                 {
02212                   state_msg.state = EMC_TASK_STATE_ESTOP_RESET;
02213                 }
02214               else
02215                 {
02216                   state_msg.state = EMC_TASK_STATE_ESTOP;
02217                 }
02218               state_msg.serial_number = ++emcCommandSerialNumber;
02219               emcCommandBuffer->write(state_msg);
02220               emcCommandWait(emcCommandSerialNumber);
02221             }
02222           break;
02223 
02224         case KEY_F(2):          // toggle servos
02225           if (oldch != ch)
02226             {
02227               if (emcStatus->task.state == EMC_TASK_STATE_ESTOP_RESET)
02228                 {
02229                   state_msg.state = EMC_TASK_STATE_ON;
02230                 }
02231               else
02232                 {
02233                   state_msg.state = EMC_TASK_STATE_OFF;
02234                 }
02235               state_msg.serial_number = ++emcCommandSerialNumber;
02236               emcCommandBuffer->write(state_msg);
02237               emcCommandWait(emcCommandSerialNumber);
02238             }
02239           break;
02240 
02241         case KEY_F(3):          // to into manual mode
02242           if (oldch != ch)
02243             {
02244               mode_msg.mode = EMC_TASK_MODE_MANUAL;
02245               mode_msg.serial_number = ++emcCommandSerialNumber;
02246               emcCommandBuffer->write(mode_msg);
02247               emcCommandWait(emcCommandSerialNumber);
02248             }
02249           break;
02250 
02251         case KEY_F(4):          // go into auto mode
02252           if (oldch != ch)
02253             {
02254               mode_msg.mode = EMC_TASK_MODE_AUTO;
02255               mode_msg.serial_number = ++emcCommandSerialNumber;
02256               emcCommandBuffer->write(mode_msg);
02257               emcCommandWait(emcCommandSerialNumber);
02258             }
02259           break;
02260 
02261         case KEY_F(5):          // go into mdi mode
02262           if (oldch != ch)
02263             {
02264               mode_msg.mode = EMC_TASK_MODE_MDI;
02265               mode_msg.serial_number = ++emcCommandSerialNumber;
02266               emcCommandBuffer->write(mode_msg);
02267               emcCommandWait(emcCommandSerialNumber);
02268             }
02269           break;
02270 
02271         case KEY_F(6):          // reset interpreter
02272           if (oldch != ch)
02273             {
02274               task_plan_init_msg.serial_number = ++emcCommandSerialNumber;
02275               emcCommandBuffer->write(task_plan_init_msg);
02276               emcCommandWait(emcCommandSerialNumber);
02277             }
02278           break;
02279 
02280         case KEY_F(7):          // toggle mist
02281           if (oldch != ch)
02282             {
02283               if (emcStatus->io.coolant.mist)
02284                 {
02285                   emc_coolant_mist_off_msg.serial_number = ++emcCommandSerialNumber;
02286                   emcCommandBuffer->write(emc_coolant_mist_off_msg);
02287                   emcCommandWait(emcCommandSerialNumber);
02288                 }
02289               else
02290                 {
02291                   emc_coolant_mist_on_msg.serial_number = ++emcCommandSerialNumber;
02292                   emcCommandBuffer->write(emc_coolant_mist_on_msg);
02293                   emcCommandWait(emcCommandSerialNumber);
02294                 }
02295             }
02296           break;
02297 
02298         case KEY_F(8):          // toggle flood
02299           if (oldch != ch)
02300             {
02301               if (emcStatus->io.coolant.flood)
02302                 {
02303                   emc_coolant_flood_off_msg.serial_number = ++emcCommandSerialNumber;
02304                   emcCommandBuffer->write(emc_coolant_flood_off_msg);
02305                   emcCommandWait(emcCommandSerialNumber);
02306                 }
02307               else
02308                 {
02309                   emc_coolant_flood_on_msg.serial_number = ++emcCommandSerialNumber;
02310                   emcCommandBuffer->write(emc_coolant_flood_on_msg);
02311                   emcCommandWait(emcCommandSerialNumber);
02312                 }
02313             }
02314           break;
02315 
02316         case KEY_F(9):          // toggle spindle forward/off
02317           if (oldch != ch)
02318             {
02319               if (emcStatus->io.spindle.direction == 0)
02320                 {
02321                   // it's off, so turn forward
02322                   emc_spindle_on_msg.speed = 1;
02323                   emc_spindle_on_msg.serial_number = ++emcCommandSerialNumber;
02324                   emcCommandBuffer->write(emc_spindle_on_msg);
02325                   emcCommandWait(emcCommandSerialNumber);
02326                 }
02327               else
02328                 {
02329                   // it's not off, so turn off
02330                   emc_spindle_off_msg.serial_number = ++emcCommandSerialNumber;
02331                   emcCommandBuffer->write(emc_spindle_off_msg);
02332                   emcCommandWait(emcCommandSerialNumber);
02333                 }
02334             }
02335           break;
02336 
02337         case KEY_F(10):         // toggle spindle reverse/off
02338           if (oldch != ch)
02339             {
02340               if (emcStatus->io.spindle.direction == 0)
02341                 {
02342                   // it's off, so turn reverse
02343                   emc_spindle_on_msg.speed = -1;
02344                   emc_spindle_on_msg.serial_number = ++emcCommandSerialNumber;
02345                   emcCommandBuffer->write(emc_spindle_on_msg);
02346                   emcCommandWait(emcCommandSerialNumber);
02347                 }
02348               else
02349                 {
02350                   // it's not off, so turn off
02351                   emc_spindle_off_msg.serial_number = ++emcCommandSerialNumber;
02352                   emcCommandBuffer->write(emc_spindle_off_msg);
02353                   emcCommandWait(emcCommandSerialNumber);
02354                 }
02355             }
02356           break;
02357 
02358         case KEY_F(11):         // spindle speed decrease
02359           if (oldch != ch)
02360             {
02361               // check for running first
02362               if (emcStatus->io.spindle.direction == 0)
02363                 break;
02364 
02365               emc_spindle_decrease_msg.serial_number = ++emcCommandSerialNumber;
02366               emcCommandBuffer->write(emc_spindle_decrease_msg);
02367               emcCommandWait(emcCommandSerialNumber);
02368               spindleChanging = 1;
02369             }
02370           break;
02371 
02372         case KEY_F(12):         // spindle speed increase
02373           if (oldch != ch)
02374             {
02375               // check for running first
02376               if (emcStatus->io.spindle.direction == 0)
02377                 break;
02378 
02379               emc_spindle_increase_msg.serial_number = ++emcCommandSerialNumber;
02380               emcCommandBuffer->write(emc_spindle_increase_msg);
02381               emcCommandWait(emcCommandSerialNumber);
02382               spindleChanging = 1;
02383             }
02384           break;
02385 
02386         case KEY_RIGHT:
02387           if (oldch != ch &&
02388               axisJogging == AXIS_NONE)
02389             {
02390               if (jogMode == JOG_INCREMENTAL)
02391                 {
02392                   emc_axis_incr_jog_msg.serial_number = ++emcCommandSerialNumber;
02393                   emc_axis_incr_jog_msg.axis = axisIndex(AXIS_X);
02394                   if (xJogPol)
02395                     emc_axis_incr_jog_msg.vel = jogSpeed / 60.0;
02396                   else
02397                     emc_axis_incr_jog_msg.vel = - jogSpeed / 60.0;
02398                   emc_axis_incr_jog_msg.incr = jogIncrement;
02399                   emcCommandBuffer->write(emc_axis_incr_jog_msg);
02400                   emcCommandWait(emcCommandSerialNumber);
02401                   // don't set axisJogging, since key up will abort
02402                 }
02403               else
02404                 {
02405                   jogMode = JOG_CONTINUOUS;
02406                   emc_axis_jog_msg.serial_number = ++emcCommandSerialNumber;
02407                   emc_axis_jog_msg.axis = axisIndex(AXIS_X);
02408                   if (xJogPol)
02409                     emc_axis_jog_msg.vel = jogSpeed / 60.0;
02410                   else
02411                     emc_axis_jog_msg.vel = - jogSpeed / 60.0;
02412                   emcCommandBuffer->write(emc_axis_jog_msg);
02413                   emcCommandWait(emcCommandSerialNumber);
02414                   axisJogging = AXIS_X;
02415                 }
02416               axisSelected = AXIS_X;
02417             }
02418           break;
02419 
02420         case KEY_LEFT:
02421           if (oldch != ch &&
02422               axisJogging == AXIS_NONE)
02423             {
02424               if (jogMode == JOG_INCREMENTAL)
02425                 {
02426                   emc_axis_incr_jog_msg.serial_number = ++emcCommandSerialNumber;
02427                   emc_axis_incr_jog_msg.axis = axisIndex(AXIS_X);
02428                   if (xJogPol)
02429                     emc_axis_incr_jog_msg.vel = - jogSpeed / 60.0;
02430                   else
02431                     emc_axis_incr_jog_msg.vel = jogSpeed / 60.0;
02432                   emc_axis_incr_jog_msg.incr = jogIncrement;
02433                   emcCommandBuffer->write(emc_axis_incr_jog_msg);
02434                   emcCommandWait(emcCommandSerialNumber);
02435                   // don't set axisJogging, since key up will abort
02436                 }
02437               else
02438                 {
02439                   jogMode = JOG_CONTINUOUS;
02440                   emc_axis_jog_msg.serial_number = ++emcCommandSerialNumber;
02441                   emc_axis_jog_msg.axis = axisIndex(AXIS_X);
02442                   if (xJogPol)
02443                     emc_axis_jog_msg.vel = - jogSpeed / 60.0;
02444                   else
02445                     emc_axis_jog_msg.vel = jogSpeed / 60.0;
02446                   emcCommandBuffer->write(emc_axis_jog_msg);
02447                   emcCommandWait(emcCommandSerialNumber);
02448                   axisJogging = AXIS_X;
02449                 }
02450               axisSelected = AXIS_X;
02451             }
02452           break;
02453 
02454         case KEY_UP:
02455           if (oldch != ch &&
02456               axisJogging == AXIS_NONE)
02457             {
02458               if (jogMode == JOG_INCREMENTAL)
02459                 {
02460                   emc_axis_incr_jog_msg.serial_number = ++emcCommandSerialNumber;
02461                   emc_axis_incr_jog_msg.axis = axisIndex(AXIS_Y);
02462                   if (yJogPol)
02463                     emc_axis_incr_jog_msg.vel = jogSpeed / 60.0;
02464                   else
02465                     emc_axis_incr_jog_msg.vel = - jogSpeed / 60.0;
02466                   emc_axis_incr_jog_msg.incr = jogIncrement;
02467                   emcCommandBuffer->write(emc_axis_incr_jog_msg);
02468                   emcCommandWait(emcCommandSerialNumber);
02469                   // don't set axisJogging, since key up will abort
02470                 }
02471               else
02472                 {
02473                   jogMode = JOG_CONTINUOUS;
02474                   emc_axis_jog_msg.serial_number = ++emcCommandSerialNumber;
02475                   emc_axis_jog_msg.axis = axisIndex(AXIS_Y);
02476                   if (yJogPol)
02477                     emc_axis_jog_msg.vel = jogSpeed / 60.0;
02478                   else
02479                     emc_axis_jog_msg.vel = - jogSpeed / 60.0;
02480                   emcCommandBuffer->write(emc_axis_jog_msg);
02481                   emcCommandWait(emcCommandSerialNumber);
02482                   axisJogging = AXIS_Y;
02483                 }
02484               axisSelected = AXIS_Y;
02485             }
02486           break;
02487 
02488         case KEY_DOWN:
02489           if (oldch != ch &&
02490               axisJogging == AXIS_NONE)
02491             {
02492               if (jogMode == JOG_INCREMENTAL)
02493                 {
02494                   emc_axis_incr_jog_msg.serial_number = ++emcCommandSerialNumber;
02495                   emc_axis_incr_jog_msg.axis = axisIndex(AXIS_Y);
02496                   if (yJogPol)
02497                     emc_axis_incr_jog_msg.vel = - jogSpeed / 60.0;
02498                   else
02499                     emc_axis_incr_jog_msg.vel = jogSpeed / 60.0;
02500                   emc_axis_incr_jog_msg.incr = jogIncrement;
02501                   emcCommandBuffer->write(emc_axis_incr_jog_msg);
02502                   emcCommandWait(emcCommandSerialNumber);
02503                   // don't set axisJogging, since key up will abort
02504                 }
02505               else
02506                 {
02507                   jogMode = JOG_CONTINUOUS;
02508                   emc_axis_jog_msg.serial_number = ++emcCommandSerialNumber;
02509                   emc_axis_jog_msg.axis = axisIndex(AXIS_Y);
02510                   if (yJogPol)
02511                     emc_axis_jog_msg.vel = - jogSpeed / 60.0;
02512                   else
02513                     emc_axis_jog_msg.vel = jogSpeed / 60.0;
02514                   emcCommandBuffer->write(emc_axis_jog_msg);
02515                   emcCommandWait(emcCommandSerialNumber);
02516                   axisJogging = AXIS_Y;
02517                 }
02518               axisSelected = AXIS_Y;
02519             }
02520           break;
02521 
02522         case KEY_PPAGE:
02523           if (oldch != ch &&
02524               axisJogging == AXIS_NONE)
02525             {
02526               if (jogMode == JOG_INCREMENTAL)
02527                 {
02528                   emc_axis_incr_jog_msg.serial_number = ++emcCommandSerialNumber;
02529                   emc_axis_incr_jog_msg.axis = axisIndex(AXIS_Z);
02530                   if (zJogPol)
02531                     emc_axis_incr_jog_msg.vel = jogSpeed / 60.0;
02532                   else
02533                     emc_axis_incr_jog_msg.vel = - jogSpeed / 60.0;
02534                   emc_axis_incr_jog_msg.incr = jogIncrement;
02535                   emcCommandBuffer->write(emc_axis_incr_jog_msg);
02536                   emcCommandWait(emcCommandSerialNumber);
02537                   // don't set axisJogging, since key up will abort
02538                 }
02539               else
02540                 {
02541                   jogMode = JOG_CONTINUOUS;
02542                   emc_axis_jog_msg.serial_number = ++emcCommandSerialNumber;
02543                   emc_axis_jog_msg.axis = axisIndex(AXIS_Z);
02544                   if (zJogPol)
02545                     emc_axis_jog_msg.vel = jogSpeed / 60.0;
02546                   else
02547                     emc_axis_jog_msg.vel = - jogSpeed / 60.0;
02548                   emcCommandBuffer->write(emc_axis_jog_msg);
02549                   emcCommandWait(emcCommandSerialNumber);
02550                   axisJogging = AXIS_Z;
02551                 }
02552               axisSelected = AXIS_Z;
02553             }
02554           break;
02555 
02556         case KEY_NPAGE:
02557           if (oldch != ch &&
02558               axisJogging == AXIS_NONE)
02559             {
02560               if (jogMode == JOG_INCREMENTAL)
02561                 {
02562                   emc_axis_incr_jog_msg.serial_number = ++emcCommandSerialNumber;
02563                   emc_axis_incr_jog_msg.axis = axisIndex(AXIS_Z);
02564                   if (zJogPol)
02565                     emc_axis_incr_jog_msg.vel = - jogSpeed / 60.0;
02566                   else
02567                     emc_axis_incr_jog_msg.vel = jogSpeed / 60.0;
02568                   emc_axis_incr_jog_msg.incr = jogIncrement;
02569                   emcCommandBuffer->write(emc_axis_incr_jog_msg);
02570                   emcCommandWait(emcCommandSerialNumber);
02571                   // don't set axisJogging, since key up will abort
02572                 }
02573               else
02574                 {
02575                   jogMode = JOG_CONTINUOUS;
02576                   emc_axis_jog_msg.serial_number = ++emcCommandSerialNumber;
02577                   emc_axis_jog_msg.axis = axisIndex(AXIS_Z);
02578                   if (zJogPol)
02579                     emc_axis_jog_msg.vel = - jogSpeed / 60.0;
02580                   else
02581                     emc_axis_jog_msg.vel = jogSpeed / 60.0;
02582                   emcCommandBuffer->write(emc_axis_jog_msg);
02583                   emcCommandWait(emcCommandSerialNumber);
02584                   axisJogging = AXIS_Z;
02585                 }
02586               axisSelected = AXIS_Z;
02587             }
02588           break;
02589 
02590         case KEY_HOME:          // home selected axis
02591           if (oldch != ch)
02592             {
02593               emc_axis_home_msg.axis = axisIndex(axisSelected);
02594               emc_axis_home_msg.serial_number = ++emcCommandSerialNumber;
02595               emcCommandBuffer->write(emc_axis_home_msg);
02596               emcCommandWait(emcCommandSerialNumber);
02597             }
02598           break;
02599 
02600         case KEY_END:           // end this program
02601           if (oldch != ch)
02602             {
02603               typing = 1;
02604               typeindex = 0;
02605               interactive = IACT_END;
02606 
02607               critFlag = 1;
02608               mvwaddstr(window, wmaxy, wbegx, line_blank);
02609               mvwaddstr(window, wmaxy, wbegx, "really quit? (y/n): ");
02610               wrefresh(window);
02611               critFlag = 0;
02612             }
02613           break;
02614 
02615         default:
02616           charHandled = 0;
02617           break;
02618         } // end of first switch (ch)
02619 
02620       // now handle interactive typing, since immediate chars have
02621       // just been handled
02622 
02623       if (typing &&
02624           ! charHandled)
02625         {
02626           if (ch == RETURN)
02627             {
02628               typing = 0;
02629               typebuffer[typeindex] = 0;
02630               typeindex = 0;
02631 
02632               critFlag = 1;
02633               mvwaddstr(window, wmaxy, wbegx, line_blank);
02634               wmove(window, wmaxy, wbegx);
02635               wrefresh(window);
02636               critFlag = 0;
02637 
02638               // now handle typed string
02639               switch (interactive)
02640                 {
02641                 case IACT_OPEN:
02642                   strcpy(task_plan_open_msg.file, typebuffer);
02643                   task_plan_open_msg.serial_number = ++emcCommandSerialNumber;
02644                   emcCommandBuffer->write(task_plan_open_msg);
02645                   emcCommandWait(emcCommandSerialNumber);
02646                   strcpy(programFile, task_plan_open_msg.file);
02647                   programOpened = 1;
02648                   if (programFp != 0)
02649                     {
02650                       fclose(programFp);
02651                     }
02652                   programFp = fopen(programFile, "r");
02653                   programLineText[0] = 0;
02654                   programFpLine = 0;
02655                   interactive = IACT_NONE;
02656                   break;
02657 
02658                 case IACT_MDI:
02659                   if (typebuffer[0] == 0)
02660                     break;      // ignore blank lines
02661                   strcpy(lastmdi, typebuffer); // save it
02662                   strcpy(task_plan_execute_msg.command, typebuffer);
02663                   task_plan_execute_msg.serial_number = ++emcCommandSerialNumber;
02664                   emcCommandBuffer->write(task_plan_execute_msg);
02665                   emcCommandWait(emcCommandSerialNumber);
02666                   interactive = IACT_NONE;
02667                   break;
02668 
02669                 case IACT_LOAD_TOOL:
02670                   strcpy(emc_tool_load_tool_table_msg.file, typebuffer);
02671                   emc_tool_load_tool_table_msg.serial_number = ++emcCommandSerialNumber;
02672                   emcCommandBuffer->write(emc_tool_load_tool_table_msg);
02673                   emcCommandWait(emcCommandSerialNumber);
02674                   interactive = IACT_NONE;
02675                   break;
02676 
02677                 case IACT_OPEN_LOG:
02678                   if (1 != sscanf(typebuffer, "%s", saveLogFile))
02679                       {
02680                         printError("bad log file");
02681                         break;
02682                       }
02683                   strcpy(emc_log_open_msg.file, saveLogFile);
02684                   emc_log_open_msg.type = saveLogType;
02685                   emc_log_open_msg.size = saveLogSize;
02686                   emc_log_open_msg.skip = saveLogSkip;
02687                   emc_log_open_msg.which = saveLogAxis;
02688                   emc_log_open_msg.serial_number = ++emcCommandSerialNumber;
02689                   emcCommandBuffer->write(emc_log_open_msg);
02690                   emcCommandWait(emcCommandSerialNumber);
02691 
02692                   interactive = IACT_NONE;
02693                   break;
02694 
02695                 case IACT_END:
02696                   if (typebuffer[0] == 'y' ||
02697                       typebuffer[0] == 'Y')
02698                     {
02699                       done = 1;
02700                     }
02701 
02702                   interactive = IACT_NONE;
02703                   break;
02704 
02705                 default:        // ignore
02706                   break;
02707                 }
02708             }
02709           else if (ch == KEY_BACKSPACE || // try all the backspace chars
02710                    ch == 8 ||
02711                    ch == 127)
02712             {
02713               if (typeindex == 0)
02714                 {
02715                   // we're at first spot-- ignore
02716                   continue;
02717                 }
02718               --typeindex;
02719               critFlag = 1;
02720               getyx(window, cury, curx);
02721               --curx;
02722               mvwaddch(window, cury, curx, ' ');
02723               wmove(window, cury, curx);
02724               wrefresh(window);
02725               critFlag = 0;
02726             }
02727           else
02728             {
02729               if (typeindex >= TYPEBUFFERSIZE - 1)
02730                 {
02731                   // we're at last spot, which we need for null-- ignore
02732                   continue;
02733                 }
02734               typebuffer[typeindex++] = ch;
02735               critFlag = 1;
02736               waddch(window, ch);
02737               wrefresh(window);
02738               critFlag = 0;
02739             }
02740 
02741           // continue with while (! done), so we skip over the normal
02742           // handling of alphanumeric chars
02743           continue;
02744 
02745         } // end of if (typing)
02746 
02747       // set up a second switch on ch, for those alphanumeric chars that
02748       // can be part of an interactive string
02749       switch (ch)
02750         {
02751         case RETURN:
02752           if (oldch != ch)
02753             {
02754               // clear all error buffers
02755               critFlag = 1;
02756               mvwaddstr(stdscr, ERR_Y, ERR_X, line_blank);
02757               mvwaddstr(helpwin, ERR_Y, ERR_X, line_blank);
02758               mvwaddstr(diagwin, ERR_Y, ERR_X, line_blank);
02759               mvwaddstr(toolwin, ERR_Y, ERR_X, line_blank);
02760               mvwaddstr(logwin, ERR_Y, ERR_X, line_blank);
02761               mvwaddstr(progwin, ERR_Y, ERR_X, line_blank);
02762               wmove(window, wmaxy, wbegx);
02763               wrefresh(window);
02764               critFlag = 0;
02765             }
02766           break;
02767 
02768         case '?':               // toggle help screen
02769           critFlag = 1;
02770           if (window == stdscr)
02771             {
02772               window = helpwin;
02773             }
02774           else if (window == helpwin)
02775             {
02776               window = toolwin;
02777             }
02778           else if (window == toolwin)
02779             {
02780               window = logwin;
02781             }
02782           else if (window == logwin)
02783             {
02784               window = diagwin;
02785             }
02786           else if (window == diagwin)
02787             {
02788               window = progwin;
02789             }
02790           else if (window == progwin)
02791             {
02792               window = stdscr;
02793             }
02794           else
02795             {
02796               window = stdscr;
02797             }
02798           critFlag = 0;
02799           clearWindow();
02800           printStatus();
02801           break;
02802 
02803         case '#':               // toggle abs/rel mode
02804           if (oldch != ch)
02805             {
02806               switch (coords)
02807                 {
02808                 case COORD_RELATIVE:
02809                   coords = COORD_ABSOLUTE;
02810                   break;
02811                 case COORD_ABSOLUTE:
02812                   coords = COORD_RELATIVE;
02813                   break;
02814                 default:
02815                   coords = COORD_RELATIVE;
02816                   break;
02817                 }
02818             }
02819           break;
02820 
02821         case '@':               // toggle cmd/act mode
02822           if (oldch != ch)
02823             {
02824               switch (posDisplay)
02825                 {
02826                 case POS_DISPLAY_ACT:
02827                   posDisplay = POS_DISPLAY_CMD;
02828                   break;
02829                 case POS_DISPLAY_CMD:
02830                   posDisplay = POS_DISPLAY_ACT;
02831                   break;
02832                 default:
02833                   posDisplay = POS_DISPLAY_ACT;
02834                   break;
02835                 }
02836             }
02837           break;
02838 
02839         case 'x':
02840         case 'X':
02841           if (oldch != ch)
02842             {
02843               if (emcStatus->task.mode == EMC_TASK_MODE_MDI)
02844                 {
02845                   typing = 1;
02846                   typeindex = 1;
02847                   typebuffer[0] = ch;
02848                   typebuffer[1] = 0;
02849                   interactive = IACT_MDI;
02850 
02851                   critFlag = 1;
02852                   mvwaddstr(window, wmaxy, wbegx, line_blank);
02853                   mvwaddstr(window, wmaxy, wbegx, "mdi command: ");
02854                   waddch(window, ch);
02855                   wrefresh(window);
02856                   critFlag = 0;
02857                 }
02858               else
02859                 {
02860                   axisSelected = AXIS_X;
02861                 }
02862             }
02863           break;
02864 
02865         case 'y':
02866         case 'Y':
02867           if (oldch != ch)
02868             {
02869               if (emcStatus->task.mode == EMC_TASK_MODE_MDI)
02870                 {
02871                   typing = 1;
02872                   typeindex = 1;
02873                   typebuffer[0] = ch;
02874                   typebuffer[1] = 0;
02875                   interactive = IACT_MDI;
02876 
02877                   critFlag = 1;
02878                   mvwaddstr(window, wmaxy, wbegx, line_blank);
02879                   mvwaddstr(window, wmaxy, wbegx, "mdi command: ");
02880                   waddch(window, ch);
02881                   wrefresh(window);
02882                   critFlag = 0;
02883                 }
02884               else
02885                 {
02886                   axisSelected = AXIS_Y;
02887                 }
02888             }
02889           break;
02890 
02891         case 'z':
02892         case 'Z':
02893           if (oldch != ch)
02894             {
02895               if (emcStatus->task.mode == EMC_TASK_MODE_MDI)
02896                 {
02897                   typing = 1;
02898                   typeindex = 1;
02899                   typebuffer[0] = ch;
02900                   typebuffer[1] = 0;
02901                   interactive = IACT_MDI;
02902 
02903                   critFlag = 1;
02904                   mvwaddstr(window, wmaxy, wbegx, line_blank);
02905                   mvwaddstr(window, wmaxy, wbegx, "mdi command: ");
02906                   waddch(window, ch);
02907                   wrefresh(window);
02908                   critFlag = 0;
02909                 }
02910               else
02911                 {
02912                   axisSelected = AXIS_Z;
02913                 }
02914             }
02915           break;
02916 
02917         case 'i':               // incremental jog toggle
02918         case 'I':
02919           if (jogMode == JOG_INCREMENTAL)
02920             {
02921               jogIncrement *= 10.0;
02922               if (jogIncrement >= 0.9)
02923                 {
02924                   jogIncrement = 0.0001;
02925                 }
02926             }
02927           jogMode = JOG_INCREMENTAL;
02928           break;
02929 
02930         case 'c':               // continuous jog
02931         case 'C':
02932           if (oldch != ch)
02933             {
02934               jogMode = JOG_CONTINUOUS;
02935             }
02936           break;
02937 
02938         case '<':
02939         case ',':
02940           if (window == logwin)
02941             {
02942               if (logtab == LOG_TYPE)
02943                 {
02944                   if (saveLogType == EMC_LOG_TYPE_AXIS_POS)
02945                     {
02946                       saveLogType = EMC_LOG_TYPE_AXIS_VEL;
02947                     }
02948                   else if (saveLogType == EMC_LOG_TYPE_AXIS_VEL)
02949                     {
02950                       saveLogType = EMC_LOG_TYPE_AXES_OUTPOS;
02951                     }
02952                   else if (saveLogType == EMC_LOG_TYPE_AXES_OUTPOS)
02953                     {
02954                       saveLogType = EMC_LOG_TYPE_AXES_INPOS;
02955                     }
02956                   else if (saveLogType == EMC_LOG_TYPE_AXES_INPOS)
02957                     {
02958                       saveLogType = EMC_LOG_TYPE_AXES_FERROR;
02959                     }
02960                   else
02961                     {
02962                       saveLogType = EMC_LOG_TYPE_AXIS_POS;
02963                     }
02964                 }
02965               else if (logtab == LOG_SIZE)
02966                 {
02967                   if (saveLogSize <= 10)
02968                     {
02969                       saveLogSize -= 1;
02970                       if (saveLogSize <= 0)
02971                         saveLogSize = 1;
02972                     }
02973                   else if (saveLogSize <= 100)
02974                     {
02975                       saveLogSize = saveLogSize - saveLogSize % 10;
02976                       saveLogSize -= 10;
02977                     }
02978                   else if (saveLogSize <= 1000)
02979                     {
02980                       saveLogSize = saveLogSize - saveLogSize % 100;
02981                       saveLogSize -= 100;
02982                     }
02983                   else
02984                     {
02985                       saveLogSize = saveLogSize - saveLogSize % 1000;
02986                       saveLogSize -= 1000;
02987                     }
02988                 }
02989               else if (logtab == LOG_SKIP)
02990                 {
02991                   if (--saveLogSkip < 0)
02992                     {
02993                       saveLogSkip = 0;
02994                     }
02995                 }
02996               else if (logtab == LOG_AXIS)
02997                 {
02998                   if (--saveLogAxis < 0)
02999                     {
03000                       saveLogAxis = 2; // X rolls back to Z
03001                     }
03002                 }
03003             }
03004           else if (window == diagwin)
03005             {
03006               if (diagtab == DIAG_USECS)
03007                 {
03008                   usecs -= 10000;
03009                   if (usecs < 10000)
03010                     usecs = 10000;
03011 
03012                   startTimer(usecs);
03013                 }
03014               else if (diagtab == DIAG_FIRST_KEYUP_DELAY)
03015                 {
03016                   FIRST_KEYUP_DELAY -= 10000;
03017                   if (FIRST_KEYUP_DELAY <= 0)
03018                     FIRST_KEYUP_DELAY = 0;
03019                 }
03020               else
03021                 {
03022                   NEXT_KEYUP_DELAY -= 10000;
03023                   if (NEXT_KEYUP_DELAY <= 0)
03024                     NEXT_KEYUP_DELAY = 0;
03025                 }
03026             }
03027           else
03028             {
03029               jogSpeed -= 1;
03030               if (jogSpeed < 1)
03031                 jogSpeed = 1;
03032             }
03033           break;
03034 
03035         case '>':
03036         case '.':
03037           if (window == logwin)
03038             {
03039               if (logtab == LOG_TYPE)
03040                 {
03041                   if (saveLogType == EMC_LOG_TYPE_AXIS_POS)
03042                     {
03043                       saveLogType = EMC_LOG_TYPE_AXES_FERROR;
03044                     }
03045                   else if (saveLogType == EMC_LOG_TYPE_AXES_FERROR)
03046                     {
03047                       saveLogType = EMC_LOG_TYPE_AXES_INPOS;
03048                     }
03049                   else if (saveLogType == EMC_LOG_TYPE_AXES_INPOS)
03050                     {
03051                       saveLogType = EMC_LOG_TYPE_AXES_OUTPOS;
03052                     }
03053                   else if (saveLogType == EMC_LOG_TYPE_AXES_OUTPOS)
03054                     {
03055                       saveLogType = EMC_LOG_TYPE_AXIS_VEL;
03056                     }
03057                   else
03058                     {
03059                       saveLogType = EMC_LOG_TYPE_AXIS_POS;
03060                     }
03061                 }
03062               else if (logtab == LOG_SIZE)
03063                 {
03064                   if (saveLogSize < 10)
03065                     {
03066                       saveLogSize += 1;
03067                     }
03068                   else if (saveLogSize < 100)
03069                     {
03070                       saveLogSize += 10;
03071                       saveLogSize = saveLogSize - saveLogSize % 10;
03072                     }
03073                   else if (saveLogSize < 1000)
03074                     {
03075                       saveLogSize += 100;
03076                       saveLogSize = saveLogSize - saveLogSize % 100;
03077                     }
03078                   else
03079                     {
03080                       saveLogSize += 1000;
03081                       saveLogSize = saveLogSize - saveLogSize % 1000;
03082                     }
03083                 }
03084               else if (logtab == LOG_SKIP)
03085                 {
03086                   saveLogSkip++;
03087                 }
03088               else if (logtab == LOG_AXIS)
03089                 {
03090                   if (++saveLogAxis > 2)
03091                     {
03092                       saveLogAxis = 0; // Z rolls back to X
03093                     }
03094                 }
03095             }
03096           else if (window == diagwin)
03097             {
03098               if (diagtab == DIAG_USECS)
03099                 {
03100                   usecs += 10000;
03101                   if (usecs > 900000)
03102                     usecs = 900000;
03103 
03104                   startTimer(usecs);
03105                 }
03106               else if (diagtab == DIAG_FIRST_KEYUP_DELAY)
03107                 {
03108                   FIRST_KEYUP_DELAY += 10000;
03109                 }
03110               else
03111                 {
03112                   NEXT_KEYUP_DELAY += 10000;
03113                 }
03114             }
03115           else
03116             {
03117               jogSpeed += 1;
03118               if (jogSpeed > TRAJ_MAX_VELOCITY * 60.0)
03119                 {
03120                   jogSpeed = TRAJ_MAX_VELOCITY * 60.0;
03121                 }
03122             }
03123           break;
03124 
03125         case '0':
03126         case '1':
03127         case '2':
03128         case '3':
03129         case '4':
03130         case '5':
03131         case '6':
03132         case '7':
03133         case '8':
03134         case '9':
03135           // feed override
03136           if (oldch != ch)
03137             {
03138               if (ch == '0')
03139                 {
03140                   emc_traj_set_scale_msg.scale = 1.0;
03141                 }
03142               else
03143                 {
03144                   emc_traj_set_scale_msg.scale = double (ch - '1' + 1) / 10.0;
03145                 }
03146               emc_traj_set_scale_msg.serial_number = ++emcCommandSerialNumber;
03147               emcCommandBuffer->write(emc_traj_set_scale_msg);
03148               emcCommandWait(emcCommandSerialNumber);
03149             }
03150           break;
03151 
03152         case 'b':               // spindle brake off
03153           if (oldch != ch)
03154             {
03155               emc_spindle_brake_release_msg.serial_number = ++emcCommandSerialNumber;
03156               emcCommandBuffer->write(emc_spindle_brake_release_msg);
03157               emcCommandWait(emcCommandSerialNumber);
03158             }
03159           break;
03160 
03161         case 'B':               // spindle brake on
03162           if (oldch != ch)
03163             {
03164               emc_spindle_brake_engage_msg.serial_number = ++emcCommandSerialNumber;
03165               emcCommandBuffer->write(emc_spindle_brake_engage_msg);
03166               emcCommandWait(emcCommandSerialNumber);
03167             }
03168           break;
03169 
03170         case 'o':
03171         case 'O':
03172           if (oldch != ch)
03173             {
03174               if (emcStatus->task.mode != EMC_TASK_MODE_AUTO)
03175                 break;
03176 
03177               typing = 1;
03178               strcpy(typebuffer, programPrefix);
03179               typeindex = strlen(programPrefix);
03180               interactive = IACT_OPEN;
03181 
03182               critFlag = 1;
03183               mvwaddstr(window, wmaxy, wbegx, line_blank);
03184               mvwaddstr(window, wmaxy, wbegx, "program to open: ");
03185               waddstr(window, typebuffer);
03186               wrefresh(window);
03187               critFlag = 0;
03188             }
03189           break;
03190 
03191         case 'r':
03192         case 'R':
03193           if (oldch != ch)
03194             {
03195               if (emcStatus->task.mode != EMC_TASK_MODE_AUTO)
03196                 break;
03197 
03198               if (! programOpened)
03199                 {
03200                   // send a request to open the last one
03201                   strcpy(task_plan_open_msg.file, programFile);
03202                   task_plan_open_msg.serial_number = ++emcCommandSerialNumber;
03203                   emcCommandBuffer->write(task_plan_open_msg);
03204                   emcCommandWait(emcCommandSerialNumber);
03205                 }
03206               task_plan_run_msg.serial_number = ++emcCommandSerialNumber;
03207               task_plan_run_msg.line = 0;
03208               emcCommandBuffer->write(task_plan_run_msg);
03209               emcCommandWait(emcCommandSerialNumber);
03210               programOpened = 0;
03211             }
03212           break;
03213 
03214         case 'p':
03215         case 'P':
03216           if (oldch != ch)
03217             {
03218               task_plan_pause_msg.serial_number = ++emcCommandSerialNumber;
03219               emcCommandBuffer->write(task_plan_pause_msg);
03220               emcCommandWait(emcCommandSerialNumber);
03221             }
03222           break;
03223 
03224         case 's':
03225         case 'S':
03226           if (oldch != ch)
03227             {
03228               task_plan_resume_msg.serial_number = ++emcCommandSerialNumber;
03229               emcCommandBuffer->write(task_plan_resume_msg);
03230               emcCommandWait(emcCommandSerialNumber);
03231             }
03232           break;
03233 
03234         case 'a':
03235         case 'A':
03236           if (oldch != ch)
03237             {
03238               task_plan_step_msg.serial_number = ++emcCommandSerialNumber;
03239               emcCommandBuffer->write(task_plan_step_msg);
03240               emcCommandWait(emcCommandSerialNumber);
03241             }
03242           break;
03243 
03244         case 'u':
03245           if (oldch != ch)
03246             {
03247               emc_lube_off_msg.serial_number = ++emcCommandSerialNumber;
03248               emcCommandBuffer->write(emc_lube_off_msg);
03249               emcCommandWait(emcCommandSerialNumber);
03250             }
03251           break;
03252 
03253         case 'U':
03254           if (oldch != ch)
03255             {
03256               emc_lube_on_msg.serial_number = ++emcCommandSerialNumber;
03257               emcCommandBuffer->write(emc_lube_on_msg);
03258               emcCommandWait(emcCommandSerialNumber);
03259             }
03260           break;
03261 
03262         case '\'':
03263         case '\"':
03264           if (oldch != ch)
03265             {
03266               if (emcStatus->task.mode != EMC_TASK_MODE_MDI)
03267                 break;
03268 
03269               typing = 1;
03270               interactive = IACT_MDI;
03271 
03272               // stuff last command
03273               strcpy(typebuffer, lastmdi);
03274               typeindex = strlen(typebuffer);
03275 
03276               critFlag = 1;
03277               mvwaddstr(window, wmaxy, wbegx, line_blank);
03278               mvwaddstr(window, wmaxy, wbegx, "mdi command: ");
03279               waddstr(window, typebuffer);
03280               wrefresh(window);
03281               critFlag = 0;
03282             }
03283           break;
03284 
03285         case 'm':
03286         case 'M':
03287         case 'g':
03288         case 'G':
03289           if (oldch != ch)
03290             {
03291               if (emcStatus->task.mode != EMC_TASK_MODE_MDI)
03292                 break;
03293 
03294               typing = 1;
03295               typeindex = 1;
03296               typebuffer[0] = ch;
03297               typebuffer[1] = 0;
03298               interactive = IACT_MDI;
03299 
03300               critFlag = 1;
03301               mvwaddstr(window, wmaxy, wbegx, line_blank);
03302               mvwaddstr(window, wmaxy, wbegx, "mdi command: ");
03303               waddch(window, ch);
03304               wrefresh(window);
03305               critFlag = 0;
03306             }
03307           break;
03308 
03309         case 'l':
03310         case 'L':
03311           if (oldch != ch)
03312             {
03313               typing = 1;
03314               typeindex = 0;
03315               interactive = IACT_LOAD_TOOL;
03316 
03317               critFlag = 1;
03318               mvwaddstr(window, wmaxy, wbegx, line_blank);
03319               mvwaddstr(window, wmaxy, wbegx, "tool file to load: ");
03320               wrefresh(window);
03321               critFlag = 0;
03322             }
03323           break;
03324 
03325         default:
03326           break;
03327         } // end of second switch (ch)
03328 
03329     } // end of while (! done)
03330 
03331   // call ^C signal handler directly to terminate cleanly
03332   quit(0);
03333 
03334   return 0;
03335 }

Generated on Sun Dec 2 15:27:41 2001 for EMC by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001