Sergey Pastor / grbl1
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers report.c Source File

report.c

00001 /*
00002   report.c - reporting and messaging methods
00003   Part of Grbl
00004 
00005   Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC
00006 
00007   Grbl is free software: you can redistribute it and/or modify
00008   it under the terms of the GNU General Public License as published by
00009   the Free Software Foundation, either version 3 of the License, or
00010   (at your option) any later version.
00011 
00012   Grbl is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015   GNU General Public License for more details.
00016 
00017   You should have received a copy of the GNU General Public License
00018   along with Grbl.  If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 /*
00022   This file functions as the primary feedback interface for Grbl. Any outgoing data, such
00023   as the protocol status messages, feedback messages, and status reports, are stored here.
00024   For the most part, these functions primarily are called from protocol.c methods. If a
00025   different style feedback is desired (i.e. JSON), then a user can change these following
00026   methods to accomodate their needs.
00027 */
00028 
00029 #include "grbl.h"
00030 
00031 
00032 // Internal report utilities to reduce flash with repetitive tasks turned into functions.
00033 void report_util_setting_prefix(uint8_t n) { serial_write('$'); print_uint8_base10(n); serial_write('='); }
00034 static void report_util_line_feed() { printPgmString(PSTR("\r\n")); }
00035 static void report_util_feedback_line_feed() { serial_write(']'); report_util_line_feed(); }
00036 static void report_util_gcode_modes_G() { printPgmString(PSTR(" G")); }
00037 static void report_util_gcode_modes_M() { printPgmString(PSTR(" M")); }
00038 // static void report_util_comment_line_feed() { serial_write(')'); report_util_line_feed(); }
00039 static void report_util_axis_values(float *axis_value) {
00040   uint8_t idx;
00041   for (idx=0; idx<N_AXIS; idx++) {
00042     printFloat_CoordValue(axis_value[idx]);
00043     if (idx < (N_AXIS-1)) { serial_write(','); }
00044   }
00045 }
00046 
00047 /*
00048 static void report_util_setting_string(uint8_t n) {
00049   serial_write(' ');
00050   serial_write('(');
00051   switch(n) {
00052     case 0: printPgmString(PSTR("stp pulse")); break;
00053     case 1: printPgmString(PSTR("idl delay")); break; 
00054     case 2: printPgmString(PSTR("stp inv")); break;
00055     case 3: printPgmString(PSTR("dir inv")); break;
00056     case 4: printPgmString(PSTR("stp en inv")); break;
00057     case 5: printPgmString(PSTR("lim inv")); break;
00058     case 6: printPgmString(PSTR("prb inv")); break;
00059     case 10: printPgmString(PSTR("rpt")); break;
00060     case 11: printPgmString(PSTR("jnc dev")); break;
00061     case 12: printPgmString(PSTR("arc tol")); break;
00062     case 13: printPgmString(PSTR("rpt inch")); break;
00063     case 20: printPgmString(PSTR("sft lim")); break;
00064     case 21: printPgmString(PSTR("hrd lim")); break;
00065     case 22: printPgmString(PSTR("hm cyc")); break;
00066     case 23: printPgmString(PSTR("hm dir inv")); break;
00067     case 24: printPgmString(PSTR("hm feed")); break;
00068     case 25: printPgmString(PSTR("hm seek")); break;
00069     case 26: printPgmString(PSTR("hm delay")); break;
00070     case 27: printPgmString(PSTR("hm pulloff")); break;
00071     case 30: printPgmString(PSTR("rpm max")); break;
00072     case 31: printPgmString(PSTR("rpm min")); break;
00073     case 32: printPgmString(PSTR("laser")); break;
00074     default:
00075       n -= AXIS_SETTINGS_START_VAL;
00076       uint8_t idx = 0;
00077       while (n >= AXIS_SETTINGS_INCREMENT) {
00078         n -= AXIS_SETTINGS_INCREMENT;
00079         idx++;
00080       }
00081       serial_write(n+'x');
00082       switch (idx) {
00083         case 0: printPgmString(PSTR(":stp/mm")); break;
00084         case 1: printPgmString(PSTR(":mm/min")); break;
00085         case 2: printPgmString(PSTR(":mm/s^2")); break;
00086         case 3: printPgmString(PSTR(":mm max")); break;
00087       }
00088       break;
00089   }
00090   report_util_comment_line_feed();
00091 }
00092 */
00093 
00094 static void report_util_uint8_setting(uint8_t n, int val) {
00095   report_util_setting_prefix(n);
00096   print_uint8_base10(val);
00097   report_util_line_feed(); // report_util_setting_string(n); 
00098 }
00099 static void report_util_float_setting(uint8_t n, float val, uint8_t n_decimal) {
00100   report_util_setting_prefix(n);
00101   printFloat(val, n_decimal);
00102   report_util_line_feed(); // report_util_setting_string(n);
00103 }
00104 
00105 // Handles the primary confirmation protocol response for streaming interfaces and human-feedback.
00106 // For every incoming line, this method responds with an 'ok' for a successful command or an
00107 // 'error:'  to indicate some error event with the line or some critical system error during
00108 // operation. Errors events can originate from the g-code parser, settings module, or asynchronously
00109 // from a critical error, such as a triggered hard limit. Interface should always monitor for these
00110 // responses.
00111 void report_status_message(uint8_t status_code)
00112 {
00113   switch(status_code) {
00114     case STATUS_OK: // STATUS_OK
00115       printPgmString(PSTR("ok\r\n")); break;
00116     default:
00117       printPgmString(PSTR("error:"));
00118       print_uint8_base10(status_code);
00119       report_util_line_feed();
00120   }
00121 }
00122 
00123 // Prints alarm messages.
00124 void report_alarm_message(uint8_t alarm_code)
00125 {
00126   printPgmString(PSTR("ALARM:"));
00127   print_uint8_base10(alarm_code);
00128   report_util_line_feed();
00129   delay_ms(500); // Force delay to ensure message clears serial write buffer.
00130 }
00131 
00132 // Prints feedback messages. This serves as a centralized method to provide additional
00133 // user feedback for things that are not of the status/alarm message protocol. These are
00134 // messages such as setup warnings, switch toggling, and how to exit alarms.
00135 // NOTE: For interfaces, messages are always placed within brackets. And if silent mode
00136 // is installed, the message number codes are less than zero.
00137 void report_feedback_message(uint8_t message_code)
00138 {
00139   printPgmString(PSTR("[MSG:"));
00140   switch(message_code) {
00141     case MESSAGE_CRITICAL_EVENT:
00142       printPgmString(PSTR("Reset to continue")); break;
00143     case MESSAGE_ALARM_LOCK:
00144       printPgmString(PSTR("'$H'|'$X' to unlock")); break;
00145     case MESSAGE_ALARM_UNLOCK:
00146       printPgmString(PSTR("Caution: Unlocked")); break;
00147     case MESSAGE_ENABLED:
00148       printPgmString(PSTR("Enabled")); break;
00149     case MESSAGE_DISABLED:
00150       printPgmString(PSTR("Disabled")); break;
00151     case MESSAGE_SAFETY_DOOR_AJAR:
00152       printPgmString(PSTR("Check Door")); break;
00153     case MESSAGE_CHECK_LIMITS:
00154       printPgmString(PSTR("Check Limits")); break;
00155     case MESSAGE_PROGRAM_END:
00156       printPgmString(PSTR("Pgm End")); break;
00157     case MESSAGE_RESTORE_DEFAULTS:
00158       printPgmString(PSTR("Restoring defaults")); break;
00159     case MESSAGE_SPINDLE_RESTORE:
00160       printPgmString(PSTR("Restoring spindle")); break;
00161     case MESSAGE_SLEEP_MODE:
00162       printPgmString(PSTR("Sleeping")); break;
00163   }
00164   report_util_feedback_line_feed();
00165 }
00166 
00167 
00168 // Welcome message
00169 void report_init_message()
00170 {
00171   printPgmString(PSTR("\r\nGrbl " GRBL_VERSION " ['$' for help]\r\n"));
00172 }
00173 
00174 // Grbl help message
00175 void report_grbl_help() {
00176   printPgmString(PSTR("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]\r\n"));    
00177 }
00178 
00179 
00180 // Grbl global settings print out.
00181 // NOTE: The numbering scheme here must correlate to storing in settings.c
00182 void report_grbl_settings() {
00183   // Print Grbl settings.
00184   report_util_uint8_setting(0,settings.pulse_microseconds);
00185   report_util_uint8_setting(1,settings.stepper_idle_lock_time);
00186   report_util_uint8_setting(2,settings.step_invert_mask);
00187   report_util_uint8_setting(3,settings.dir_invert_mask);
00188   report_util_uint8_setting(4,bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE));
00189   report_util_uint8_setting(5,bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS));
00190   report_util_uint8_setting(6,bit_istrue(settings.flags,BITFLAG_INVERT_PROBE_PIN));
00191   report_util_uint8_setting(10,settings.status_report_mask);
00192   report_util_float_setting(11,settings.junction_deviation,N_DECIMAL_SETTINGVALUE);
00193   report_util_float_setting(12,settings.arc_tolerance,N_DECIMAL_SETTINGVALUE);
00194   report_util_uint8_setting(13,bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));
00195   report_util_uint8_setting(20,bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE));
00196   report_util_uint8_setting(21,bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
00197   report_util_uint8_setting(22,bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
00198   report_util_uint8_setting(23,settings.homing_dir_mask);
00199   report_util_float_setting(24,settings.homing_feed_rate,N_DECIMAL_SETTINGVALUE);
00200   report_util_float_setting(25,settings.homing_seek_rate,N_DECIMAL_SETTINGVALUE);
00201   report_util_uint8_setting(26,settings.homing_debounce_delay);
00202   report_util_float_setting(27,settings.homing_pulloff,N_DECIMAL_SETTINGVALUE);
00203   report_util_float_setting(30,settings.rpm_max,N_DECIMAL_RPMVALUE);
00204   report_util_float_setting(31,settings.rpm_min,N_DECIMAL_RPMVALUE);
00205   #ifdef VARIABLE_SPINDLE
00206     report_util_uint8_setting(32,bit_istrue(settings.flags,BITFLAG_LASER_MODE));
00207   #else
00208     report_util_uint8_setting(32,0);
00209   #endif
00210   // Print axis settings
00211   uint8_t idx, set_idx;
00212   uint8_t val = AXIS_SETTINGS_START_VAL;
00213   for (set_idx=0; set_idx<AXIS_N_SETTINGS; set_idx++) {
00214     for (idx=0; idx<N_AXIS; idx++) {
00215       switch (set_idx) {
00216         case 0: report_util_float_setting(val+idx,settings.steps_per_mm[idx],N_DECIMAL_SETTINGVALUE); break;
00217         case 1: report_util_float_setting(val+idx,settings.max_rate[idx],N_DECIMAL_SETTINGVALUE); break;
00218         case 2: report_util_float_setting(val+idx,settings.acceleration[idx]/(60*60),N_DECIMAL_SETTINGVALUE); break;
00219         case 3: report_util_float_setting(val+idx,-settings.max_travel[idx],N_DECIMAL_SETTINGVALUE); break;
00220       }
00221     }
00222     val += AXIS_SETTINGS_INCREMENT;
00223   }
00224 }
00225 
00226 
00227 // Prints current probe parameters. Upon a probe command, these parameters are updated upon a
00228 // successful probe or upon a failed probe with the G38.3 without errors command (if supported).
00229 // These values are retained until Grbl is power-cycled, whereby they will be re-zeroed.
00230 void report_probe_parameters()
00231 {
00232   // Report in terms of machine position.
00233   printPgmString(PSTR("[PRB:"));
00234   float print_position[N_AXIS];
00235   system_convert_array_steps_to_mpos(print_position,sys_probe_position);
00236   report_util_axis_values(print_position);
00237   serial_write(':');
00238   print_uint8_base10(sys.probe_succeeded);
00239   report_util_feedback_line_feed();
00240 }
00241 
00242 
00243 // Prints Grbl NGC parameters (coordinate offsets, probing)
00244 void report_ngc_parameters()
00245 {
00246   float coord_data[N_AXIS];
00247   uint8_t coord_select;
00248   for (coord_select = 0; coord_select <= SETTING_INDEX_NCOORD; coord_select++) {
00249     if (!(settings_read_coord_data(coord_select,coord_data))) {
00250       report_status_message(STATUS_SETTING_READ_FAIL);
00251       return;
00252     }
00253     printPgmString(PSTR("[G"));
00254     switch (coord_select) {
00255       case 6: printPgmString(PSTR("28")); break;
00256       case 7: printPgmString(PSTR("30")); break;
00257       default: print_uint8_base10(coord_select+54); break; // G54-G59
00258     }
00259     serial_write(':');
00260     report_util_axis_values(coord_data);
00261     report_util_feedback_line_feed();
00262   }
00263   printPgmString(PSTR("[G92:")); // Print G92,G92.1 which are not persistent in memory
00264   report_util_axis_values(gc_state.coord_offset);
00265   report_util_feedback_line_feed();
00266   printPgmString(PSTR("[TLO:")); // Print tool length offset value
00267   printFloat_CoordValue(gc_state.tool_length_offset);
00268   report_util_feedback_line_feed();
00269   report_probe_parameters(); // Print probe parameters. Not persistent in memory.
00270 }
00271 
00272 
00273 // Print current gcode parser mode state
00274 void report_gcode_modes()
00275 {
00276   printPgmString(PSTR("[GC:G"));
00277   if (gc_state.modal.motion >= MOTION_MODE_PROBE_TOWARD) {
00278     printPgmString(PSTR("38."));
00279     print_uint8_base10(gc_state.modal.motion - (MOTION_MODE_PROBE_TOWARD-2));
00280   } else {
00281     print_uint8_base10(gc_state.modal.motion);
00282   }
00283 
00284   report_util_gcode_modes_G();
00285   print_uint8_base10(gc_state.modal.coord_select+54);
00286 
00287   report_util_gcode_modes_G();
00288   print_uint8_base10(gc_state.modal.plane_select+17);
00289 
00290   report_util_gcode_modes_G();
00291   print_uint8_base10(21-gc_state.modal.units);
00292 
00293   report_util_gcode_modes_G();
00294   print_uint8_base10(gc_state.modal.distance+90);
00295 
00296   report_util_gcode_modes_G();
00297   print_uint8_base10(94-gc_state.modal.feed_rate);
00298 
00299   if (gc_state.modal.program_flow) {
00300     report_util_gcode_modes_M();
00301     switch (gc_state.modal.program_flow) {
00302       case PROGRAM_FLOW_PAUSED : serial_write('0'); break;
00303       // case PROGRAM_FLOW_OPTIONAL_STOP : serial_write('1'); break; // M1 is ignored and not supported.
00304       case PROGRAM_FLOW_COMPLETED_M2 : 
00305       case PROGRAM_FLOW_COMPLETED_M30 : 
00306         print_uint8_base10(gc_state.modal.program_flow);
00307         break;
00308     }
00309   }
00310 
00311   report_util_gcode_modes_M();
00312   switch (gc_state.modal.spindle) {
00313     case SPINDLE_ENABLE_CW : serial_write('3'); break;
00314     case SPINDLE_ENABLE_CCW : serial_write('4'); break;
00315     case SPINDLE_DISABLE : serial_write('5'); break;
00316   }
00317 
00318   report_util_gcode_modes_M();
00319   #ifdef ENABLE_M7
00320     if (gc_state.modal.coolant) { // Note: Multiple coolant states may be active at the same time.
00321       if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_MIST) { report_util_gcode_modes_M(); serial_write('7'); }
00322       if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_FLOOD) { report_util_gcode_modes_M(); serial_write('8'); }
00323     } else { report_util_gcode_modes_M(); serial_write('9'); }
00324   #else
00325     report_util_gcode_modes_M();
00326     if (gc_state.modal.coolant) { serial_write('8'); }
00327     else { serial_write('9'); }
00328   #endif
00329 
00330     #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
00331         if (sys.override_ctrl == OVERRIDE_PARKING_MOTION) {
00332             report_util_gcode_modes_M();
00333             print_uint8_base10(56);
00334         }
00335     #endif
00336 
00337   printPgmString(PSTR(" T"));
00338   print_uint8_base10(gc_state.tool);
00339 
00340   printPgmString(PSTR(" F"));
00341   printFloat_RateValue(gc_state.feed_rate);
00342 
00343   #ifdef VARIABLE_SPINDLE
00344     printPgmString(PSTR(" S"));
00345     printFloat(gc_state.spindle_speed,N_DECIMAL_RPMVALUE);
00346   #endif
00347 
00348   report_util_feedback_line_feed();
00349 }
00350 
00351 // Prints specified startup line
00352 void report_startup_line(uint8_t n, char *line)
00353 {
00354   printPgmString(PSTR("$N"));
00355   print_uint8_base10(n);
00356   serial_write('=');
00357   printString(line);
00358   report_util_line_feed();
00359 }
00360 
00361 void report_execute_startup_message(char *line, uint8_t status_code)
00362 {
00363   serial_write('>');
00364   printString(line);
00365   serial_write(':');
00366   report_status_message(status_code);
00367 }
00368 
00369 // Prints build info line
00370 void report_build_info(char *line)
00371 {
00372   printPgmString(PSTR("[VER:" GRBL_VERSION "." GRBL_VERSION_BUILD ":"));
00373   printString(line);
00374   report_util_feedback_line_feed();
00375   printPgmString(PSTR("[OPT:")); // Generate compile-time build option list
00376   #ifdef VARIABLE_SPINDLE
00377     serial_write('V');
00378   #endif
00379   #ifdef USE_LINE_NUMBERS
00380     serial_write('N');
00381   #endif
00382   #ifdef ENABLE_M7
00383     serial_write('M');
00384   #endif
00385   #ifdef COREXY
00386     serial_write('C');
00387   #endif
00388   #ifdef PARKING_ENABLE
00389     serial_write('P');
00390   #endif
00391   #ifdef HOMING_FORCE_SET_ORIGIN
00392     serial_write('Z');
00393   #endif
00394   #ifdef HOMING_SINGLE_AXIS_COMMANDS
00395     serial_write('H');
00396   #endif
00397   #ifdef LIMITS_TWO_SWITCHES_ON_AXES
00398     serial_write('T');
00399   #endif
00400   #ifdef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES
00401     serial_write('A');
00402   #endif
00403     #ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN
00404         serial_write('D');
00405     #endif
00406     #ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED
00407         serial_write('0');
00408     #endif
00409     #ifdef ENABLE_SOFTWARE_DEBOUNCE
00410         serial_write('S');
00411     #endif
00412     #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
00413         serial_write('R');
00414     #endif
00415     #ifndef ENABLE_RESTORE_EEPROM_WIPE_ALL // NOTE: Shown when disabled.
00416     serial_write('*');
00417   #endif
00418   #ifndef ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS // NOTE: Shown when disabled.
00419     serial_write('$');
00420   #endif
00421   #ifndef ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS // NOTE: Shown when disabled.
00422     serial_write('#');
00423   #endif
00424   #ifndef ENABLE_BUILD_INFO_WRITE_COMMAND // NOTE: Shown when disabled.
00425     serial_write('I');
00426   #endif
00427   #ifndef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE // NOTE: Shown when disabled.
00428     serial_write('E');
00429   #endif
00430   #ifndef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE // NOTE: Shown when disabled.
00431     serial_write('W');
00432   #endif
00433     #ifndef HOMING_INIT_LOCK
00434         serial_write('L');
00435     #endif
00436 
00437   // NOTE: Compiled values, like override increments/max/min values, may be added at some point later.
00438     serial_write(',');
00439     print_uint8_base10(BLOCK_BUFFER_SIZE - 1);
00440     serial_write(',');
00441     print_uint8_base10(RX_BUFFER_SIZE);
00442 
00443     report_util_feedback_line_feed();
00444 }
00445 
00446 
00447 // Prints the character string line Grbl has received from the user, which has been pre-parsed,
00448 // and has been sent into protocol_execute_line() routine to be executed by Grbl.
00449 void report_echo_line_received(char *line)
00450 {
00451   printPgmString(PSTR("[echo: ")); printString(line);
00452   report_util_feedback_line_feed();
00453 }
00454 
00455 
00456  // Prints real-time data. This function grabs a real-time snapshot of the stepper subprogram
00457  // and the actual location of the CNC machine. Users may change the following function to their
00458  // specific needs, but the desired real-time data report must be as short as possible. This is
00459  // requires as it minimizes the computational overhead and allows grbl to keep running smoothly,
00460  // especially during g-code programs with fast, short line segments and high frequency reports (5-20Hz).
00461 void report_realtime_status()
00462 {
00463   uint8_t idx;
00464   int32_t current_position[N_AXIS]; // Copy current state of the system position variable
00465   memcpy(current_position, sys_position, sizeof(sys_position));
00466   float print_position[N_AXIS];
00467   system_convert_array_steps_to_mpos(print_position, current_position);
00468 
00469   // Report current machine state and sub-states
00470   serial_write('<');
00471   switch (sys.state) {
00472   case STATE_IDLE: printPgmString(PSTR("Idle")); break;
00473   case STATE_CYCLE: printPgmString(PSTR("Run")); break;
00474   case STATE_HOLD:
00475     if (!(sys.suspend & SUSPEND_JOG_CANCEL)) {
00476       printPgmString(PSTR("Hold:"));
00477       if (sys.suspend & SUSPEND_HOLD_COMPLETE) { serial_write('0'); } // Ready to resume
00478       else { serial_write('1'); } // Actively holding
00479       break;
00480     } // Continues to print jog state during jog cancel.
00481   case STATE_JOG: printPgmString(PSTR("Jog")); break;
00482   case STATE_HOMING: printPgmString(PSTR("Home")); break;
00483   case STATE_ALARM: printPgmString(PSTR("Alarm")); break;
00484   case STATE_CHECK_MODE: printPgmString(PSTR("Check")); break;
00485   case STATE_SAFETY_DOOR:
00486     printPgmString(PSTR("Door:"));
00487     if (sys.suspend & SUSPEND_INITIATE_RESTORE) {
00488       serial_write('3'); // Restoring
00489     }
00490     else {
00491       if (sys.suspend & SUSPEND_RETRACT_COMPLETE) {
00492         if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) {
00493           serial_write('1'); // Door ajar
00494         }
00495         else {
00496           serial_write('0');
00497         } // Door closed and ready to resume
00498       }
00499       else {
00500         serial_write('2'); // Retracting
00501       }
00502     }
00503     break;
00504   case STATE_SLEEP: printPgmString(PSTR("Sleep")); break;
00505   }
00506 
00507   float wco[N_AXIS];
00508   if (bit_isfalse(settings.status_report_mask, BITFLAG_RT_STATUS_POSITION_TYPE) ||
00509     (sys.report_wco_counter == 0)) {
00510     for (idx = 0; idx< N_AXIS; idx++) {
00511       // Apply work coordinate offsets and tool length offset to current position.
00512       wco[idx] = gc_state.coord_system[idx] + gc_state.coord_offset[idx];
00513       if (idx == TOOL_LENGTH_OFFSET_AXIS) { wco[idx] += gc_state.tool_length_offset; }
00514       if (bit_isfalse(settings.status_report_mask, BITFLAG_RT_STATUS_POSITION_TYPE)) {
00515         print_position[idx] -= wco[idx];
00516       }
00517     }
00518   }
00519 
00520   // Report machine position
00521   if (bit_istrue(settings.status_report_mask, BITFLAG_RT_STATUS_POSITION_TYPE)) {
00522     printPgmString(PSTR("|MPos:"));
00523   }
00524   else {
00525     printPgmString(PSTR("|WPos:"));
00526   }
00527   report_util_axis_values(print_position);
00528 
00529   // Returns planner and serial read buffer states.
00530 #ifdef REPORT_FIELD_BUFFER_STATE
00531   if (bit_istrue(settings.status_report_mask, BITFLAG_RT_STATUS_BUFFER_STATE)) {
00532     printPgmString(PSTR("|Bf:"));
00533     print_uint8_base10(plan_get_block_buffer_available());
00534     serial_write(',');
00535     print_uint8_base10(serial_get_rx_buffer_available());
00536   }
00537 #endif
00538 
00539 #ifdef USE_LINE_NUMBERS
00540 #ifdef REPORT_FIELD_LINE_NUMBERS
00541   // Report current line number
00542   plan_block_t * cur_block = plan_get_current_block();
00543   if (cur_block != NULL) {
00544     uint32_t ln = cur_block->line_number;
00545     if (ln > 0) {
00546       printPgmString(PSTR("|Ln:"));
00547       printInteger(ln);
00548     }
00549   }
00550 #endif
00551 #endif
00552 
00553   // Report realtime feed speed
00554 #ifdef REPORT_FIELD_CURRENT_FEED_SPEED
00555 #ifdef VARIABLE_SPINDLE
00556   printPgmString(PSTR("|FS:"));
00557   printFloat_RateValue(st_get_realtime_rate());
00558   serial_write(',');
00559   printFloat(sys.spindle_speed, N_DECIMAL_RPMVALUE);
00560 #else
00561   printPgmString(PSTR("|F:"));
00562   printFloat_RateValue(st_get_realtime_rate());
00563 #endif      
00564 #endif
00565 
00566 #ifdef REPORT_FIELD_PIN_STATE
00567   uint8_t lim_pin_state = limits_get_state();
00568   uint8_t ctrl_pin_state = system_control_get_state();
00569   uint8_t prb_pin_state = probe_get_state();
00570   if (lim_pin_state | ctrl_pin_state | prb_pin_state) {
00571     printPgmString(PSTR("|Pn:"));
00572     if (prb_pin_state) { serial_write('P'); }
00573     if (lim_pin_state) {
00574       if (bit_istrue(lim_pin_state, bit(X_AXIS))) { serial_write('X'); }
00575       if (bit_istrue(lim_pin_state, bit(Y_AXIS))) { serial_write('Y'); }
00576       if (bit_istrue(lim_pin_state, bit(Z_AXIS))) { serial_write('Z'); }
00577     }
00578     if (ctrl_pin_state) {
00579 #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
00580       if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_SAFETY_DOOR)) { serial_write('D'); }
00581 #endif
00582       if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_RESET)) { serial_write('R'); }
00583       if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_FEED_HOLD)) { serial_write('H'); }
00584       if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_CYCLE_START)) { serial_write('S'); }
00585     }
00586   }
00587 #endif
00588 
00589 #ifdef REPORT_FIELD_WORK_COORD_OFFSET
00590   if (sys.report_wco_counter > 0) { sys.report_wco_counter--; }
00591   else {
00592     if (sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) {
00593       sys.report_wco_counter = (REPORT_WCO_REFRESH_BUSY_COUNT - 1); // Reset counter for slow refresh
00594     }
00595     else { sys.report_wco_counter = (REPORT_WCO_REFRESH_IDLE_COUNT - 1); }
00596     if (sys.report_ovr_counter == 0) { sys.report_ovr_counter = 1; } // Set override on next report.
00597     printPgmString(PSTR("|WCO:"));
00598     report_util_axis_values(wco);
00599   }
00600 #endif
00601 
00602   #ifdef REPORT_FIELD_OVERRIDES
00603     if (sys.report_ovr_counter > 0) { sys.report_ovr_counter--; }
00604     else {
00605       if (sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) {
00606         sys.report_ovr_counter = (REPORT_OVR_REFRESH_BUSY_COUNT - 1); // Reset counter for slow refresh
00607       }
00608       else { sys.report_ovr_counter = (REPORT_OVR_REFRESH_IDLE_COUNT - 1); }
00609       printPgmString(PSTR("|Ov:"));
00610       print_uint8_base10(sys.f_override);
00611       serial_write(',');
00612       print_uint8_base10(sys.r_override);
00613       serial_write(',');
00614       print_uint8_base10(sys.spindle_speed_ovr);
00615 
00616       uint8_t sp_state = spindle_get_state();
00617       uint8_t cl_state = coolant_get_state();
00618       if (sp_state || cl_state) {
00619         printPgmString(PSTR("|A:"));
00620         if (sp_state) { // != SPINDLE_STATE_DISABLE
00621           #ifdef VARIABLE_SPINDLE 
00622             #ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN
00623               serial_write('S'); // CW
00624             #else
00625               if (sp_state == SPINDLE_STATE_CW) { serial_write('S'); } // CW
00626               else { serial_write('C'); } // CCW
00627             #endif
00628           #else
00629             if (sp_state & SPINDLE_STATE_CW) { serial_write('S'); } // CW
00630             else { serial_write('C'); } // CCW
00631           #endif
00632         }
00633         if (cl_state & COOLANT_STATE_FLOOD) { serial_write('F'); }
00634         #ifdef ENABLE_M7
00635           if (cl_state & COOLANT_STATE_MIST) { serial_write('M'); }
00636         #endif
00637       }
00638     }
00639   #endif
00640 
00641   serial_write('>');
00642   report_util_line_feed();
00643 }
00644 
00645 
00646 #ifdef DEBUG
00647   void report_realtime_debug()
00648   {
00649 
00650   }
00651 #endif