Luigi Santivetti | 69972f9 | 2019-11-12 22:55:40 +0000 | [diff] [blame] | 1 | /* |
| 2 | report.c - reporting and messaging methods |
| 3 | Part of Grbl |
| 4 | |
| 5 | Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC |
| 6 | |
| 7 | Grbl is free software: you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation, either version 3 of the License, or |
| 10 | (at your option) any later version. |
| 11 | |
| 12 | Grbl is distributed in the hope that it will be useful, |
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | GNU General Public License for more details. |
| 16 | |
| 17 | You should have received a copy of the GNU General Public License |
| 18 | along with Grbl. If not, see <http://www.gnu.org/licenses/>. |
| 19 | */ |
| 20 | |
| 21 | /* |
| 22 | This file functions as the primary feedback interface for Grbl. Any outgoing data, such |
| 23 | as the protocol status messages, feedback messages, and status reports, are stored here. |
| 24 | For the most part, these functions primarily are called from protocol.c methods. If a |
| 25 | different style feedback is desired (i.e. JSON), then a user can change these following |
| 26 | methods to accomodate their needs. |
| 27 | */ |
| 28 | |
| 29 | #include "grbl.h" |
| 30 | |
| 31 | |
| 32 | // Internal report utilities to reduce flash with repetitive tasks turned into functions. |
| 33 | void report_util_setting_prefix(uint8_t n) { serial_write('$'); print_uint8_base10(n); serial_write('='); } |
| 34 | static void report_util_line_feed() { printPgmString(PSTR("\r\n")); } |
| 35 | static void report_util_feedback_line_feed() { serial_write(']'); report_util_line_feed(); } |
| 36 | static void report_util_gcode_modes_G() { printPgmString(PSTR(" G")); } |
| 37 | static void report_util_gcode_modes_M() { printPgmString(PSTR(" M")); } |
| 38 | // static void report_util_comment_line_feed() { serial_write(')'); report_util_line_feed(); } |
| 39 | static void report_util_axis_values(float *axis_value) { |
| 40 | uint8_t idx; |
| 41 | for (idx=0; idx<N_AXIS; idx++) { |
| 42 | printFloat_CoordValue(axis_value[idx]); |
| 43 | if (idx < (N_AXIS-1)) { serial_write(','); } |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | /* |
| 48 | static void report_util_setting_string(uint8_t n) { |
| 49 | serial_write(' '); |
| 50 | serial_write('('); |
| 51 | switch(n) { |
| 52 | case 0: printPgmString(PSTR("stp pulse")); break; |
| 53 | case 1: printPgmString(PSTR("idl delay")); break; |
| 54 | case 2: printPgmString(PSTR("stp inv")); break; |
| 55 | case 3: printPgmString(PSTR("dir inv")); break; |
| 56 | case 4: printPgmString(PSTR("stp en inv")); break; |
| 57 | case 5: printPgmString(PSTR("lim inv")); break; |
| 58 | case 6: printPgmString(PSTR("prb inv")); break; |
| 59 | case 10: printPgmString(PSTR("rpt")); break; |
| 60 | case 11: printPgmString(PSTR("jnc dev")); break; |
| 61 | case 12: printPgmString(PSTR("arc tol")); break; |
| 62 | case 13: printPgmString(PSTR("rpt inch")); break; |
| 63 | case 20: printPgmString(PSTR("sft lim")); break; |
| 64 | case 21: printPgmString(PSTR("hrd lim")); break; |
| 65 | case 22: printPgmString(PSTR("hm cyc")); break; |
| 66 | case 23: printPgmString(PSTR("hm dir inv")); break; |
| 67 | case 24: printPgmString(PSTR("hm feed")); break; |
| 68 | case 25: printPgmString(PSTR("hm seek")); break; |
| 69 | case 26: printPgmString(PSTR("hm delay")); break; |
| 70 | case 27: printPgmString(PSTR("hm pulloff")); break; |
| 71 | case 30: printPgmString(PSTR("rpm max")); break; |
| 72 | case 31: printPgmString(PSTR("rpm min")); break; |
| 73 | case 32: printPgmString(PSTR("laser")); break; |
| 74 | default: |
| 75 | n -= AXIS_SETTINGS_START_VAL; |
| 76 | uint8_t idx = 0; |
| 77 | while (n >= AXIS_SETTINGS_INCREMENT) { |
| 78 | n -= AXIS_SETTINGS_INCREMENT; |
| 79 | idx++; |
| 80 | } |
| 81 | serial_write(n+'x'); |
| 82 | switch (idx) { |
| 83 | case 0: printPgmString(PSTR(":stp/mm")); break; |
| 84 | case 1: printPgmString(PSTR(":mm/min")); break; |
| 85 | case 2: printPgmString(PSTR(":mm/s^2")); break; |
| 86 | case 3: printPgmString(PSTR(":mm max")); break; |
| 87 | } |
| 88 | break; |
| 89 | } |
| 90 | report_util_comment_line_feed(); |
| 91 | } |
| 92 | */ |
| 93 | |
| 94 | static void report_util_uint8_setting(uint8_t n, int val) { |
| 95 | report_util_setting_prefix(n); |
| 96 | print_uint8_base10(val); |
| 97 | report_util_line_feed(); // report_util_setting_string(n); |
| 98 | } |
| 99 | static void report_util_float_setting(uint8_t n, float val, uint8_t n_decimal) { |
| 100 | report_util_setting_prefix(n); |
| 101 | printFloat(val,n_decimal); |
| 102 | report_util_line_feed(); // report_util_setting_string(n); |
| 103 | } |
| 104 | |
| 105 | |
| 106 | // Handles the primary confirmation protocol response for streaming interfaces and human-feedback. |
| 107 | // For every incoming line, this method responds with an 'ok' for a successful command or an |
| 108 | // 'error:' to indicate some error event with the line or some critical system error during |
| 109 | // operation. Errors events can originate from the g-code parser, settings module, or asynchronously |
| 110 | // from a critical error, such as a triggered hard limit. Interface should always monitor for these |
| 111 | // responses. |
| 112 | void report_status_message(uint8_t status_code) |
| 113 | { |
| 114 | switch(status_code) { |
| 115 | case STATUS_OK: // STATUS_OK |
| 116 | printPgmString(PSTR("ok\r\n")); break; |
| 117 | default: |
| 118 | printPgmString(PSTR("error:")); |
| 119 | print_uint8_base10(status_code); |
| 120 | report_util_line_feed(); |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | // Prints alarm messages. |
| 125 | void report_alarm_message(uint8_t alarm_code) |
| 126 | { |
| 127 | printPgmString(PSTR("ALARM:")); |
| 128 | print_uint8_base10(alarm_code); |
| 129 | report_util_line_feed(); |
| 130 | delay_ms(500); // Force delay to ensure message clears serial write buffer. |
| 131 | } |
| 132 | |
| 133 | // Prints feedback messages. This serves as a centralized method to provide additional |
| 134 | // user feedback for things that are not of the status/alarm message protocol. These are |
| 135 | // messages such as setup warnings, switch toggling, and how to exit alarms. |
| 136 | // NOTE: For interfaces, messages are always placed within brackets. And if silent mode |
| 137 | // is installed, the message number codes are less than zero. |
| 138 | void report_feedback_message(uint8_t message_code) |
| 139 | { |
| 140 | printPgmString(PSTR("[MSG:")); |
| 141 | switch(message_code) { |
| 142 | case MESSAGE_CRITICAL_EVENT: |
| 143 | printPgmString(PSTR("Reset to continue")); break; |
| 144 | case MESSAGE_ALARM_LOCK: |
| 145 | printPgmString(PSTR("'$H'|'$X' to unlock")); break; |
| 146 | case MESSAGE_ALARM_UNLOCK: |
| 147 | printPgmString(PSTR("Caution: Unlocked")); break; |
| 148 | case MESSAGE_ENABLED: |
| 149 | printPgmString(PSTR("Enabled")); break; |
| 150 | case MESSAGE_DISABLED: |
| 151 | printPgmString(PSTR("Disabled")); break; |
| 152 | case MESSAGE_SAFETY_DOOR_AJAR: |
| 153 | printPgmString(PSTR("Check Door")); break; |
| 154 | case MESSAGE_CHECK_LIMITS: |
| 155 | printPgmString(PSTR("Check Limits")); break; |
| 156 | case MESSAGE_PROGRAM_END: |
| 157 | printPgmString(PSTR("Pgm End")); break; |
| 158 | case MESSAGE_RESTORE_DEFAULTS: |
| 159 | printPgmString(PSTR("Restoring defaults")); break; |
| 160 | case MESSAGE_SPINDLE_RESTORE: |
| 161 | printPgmString(PSTR("Restoring spindle")); break; |
| 162 | case MESSAGE_SLEEP_MODE: |
| 163 | printPgmString(PSTR("Sleeping")); break; |
| 164 | } |
| 165 | report_util_feedback_line_feed(); |
| 166 | } |
| 167 | |
| 168 | |
| 169 | // Welcome message |
| 170 | void report_init_message() |
| 171 | { |
| 172 | printPgmString(PSTR("\r\nGrbl " GRBL_VERSION " ['$' for help]\r\n")); |
| 173 | } |
| 174 | |
| 175 | // Grbl help message |
| 176 | void report_grbl_help() { |
| 177 | printPgmString(PSTR("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]\r\n")); |
| 178 | } |
| 179 | |
| 180 | |
| 181 | // Grbl global settings print out. |
| 182 | // NOTE: The numbering scheme here must correlate to storing in settings.c |
| 183 | void report_grbl_settings() { |
| 184 | // Print Grbl settings. |
| 185 | report_util_uint8_setting(0,settings.pulse_microseconds); |
| 186 | report_util_uint8_setting(1,settings.stepper_idle_lock_time); |
| 187 | report_util_uint8_setting(2,settings.step_invert_mask); |
| 188 | report_util_uint8_setting(3,settings.dir_invert_mask); |
| 189 | report_util_uint8_setting(4,bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)); |
| 190 | report_util_uint8_setting(5,bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)); |
| 191 | report_util_uint8_setting(6,bit_istrue(settings.flags,BITFLAG_INVERT_PROBE_PIN)); |
| 192 | report_util_uint8_setting(10,settings.status_report_mask); |
| 193 | report_util_float_setting(11,settings.junction_deviation,N_DECIMAL_SETTINGVALUE); |
| 194 | report_util_float_setting(12,settings.arc_tolerance,N_DECIMAL_SETTINGVALUE); |
| 195 | report_util_uint8_setting(13,bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)); |
| 196 | report_util_uint8_setting(20,bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)); |
| 197 | report_util_uint8_setting(21,bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)); |
| 198 | report_util_uint8_setting(22,bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)); |
| 199 | report_util_uint8_setting(23,settings.homing_dir_mask); |
| 200 | report_util_float_setting(24,settings.homing_feed_rate,N_DECIMAL_SETTINGVALUE); |
| 201 | report_util_float_setting(25,settings.homing_seek_rate,N_DECIMAL_SETTINGVALUE); |
| 202 | report_util_uint8_setting(26,settings.homing_debounce_delay); |
| 203 | report_util_float_setting(27,settings.homing_pulloff,N_DECIMAL_SETTINGVALUE); |
| 204 | report_util_float_setting(30,settings.rpm_max,N_DECIMAL_RPMVALUE); |
| 205 | report_util_float_setting(31,settings.rpm_min,N_DECIMAL_RPMVALUE); |
| 206 | #ifdef VARIABLE_SPINDLE |
| 207 | report_util_uint8_setting(32,bit_istrue(settings.flags,BITFLAG_LASER_MODE)); |
| 208 | #else |
| 209 | report_util_uint8_setting(32,0); |
| 210 | #endif |
| 211 | // Print axis settings |
| 212 | uint8_t idx, set_idx; |
| 213 | uint8_t val = AXIS_SETTINGS_START_VAL; |
| 214 | for (set_idx=0; set_idx<AXIS_N_SETTINGS; set_idx++) { |
| 215 | for (idx=0; idx<N_AXIS; idx++) { |
| 216 | switch (set_idx) { |
| 217 | case 0: report_util_float_setting(val+idx,settings.steps_per_mm[idx],N_DECIMAL_SETTINGVALUE); break; |
| 218 | case 1: report_util_float_setting(val+idx,settings.max_rate[idx],N_DECIMAL_SETTINGVALUE); break; |
| 219 | case 2: report_util_float_setting(val+idx,settings.acceleration[idx]/(60*60),N_DECIMAL_SETTINGVALUE); break; |
| 220 | case 3: report_util_float_setting(val+idx,-settings.max_travel[idx],N_DECIMAL_SETTINGVALUE); break; |
| 221 | } |
| 222 | } |
| 223 | val += AXIS_SETTINGS_INCREMENT; |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | |
| 228 | // Prints current probe parameters. Upon a probe command, these parameters are updated upon a |
| 229 | // successful probe or upon a failed probe with the G38.3 without errors command (if supported). |
| 230 | // These values are retained until Grbl is power-cycled, whereby they will be re-zeroed. |
| 231 | void report_probe_parameters() |
| 232 | { |
| 233 | // Report in terms of machine position. |
| 234 | printPgmString(PSTR("[PRB:")); |
| 235 | float print_position[N_AXIS]; |
| 236 | system_convert_array_steps_to_mpos(print_position,sys_probe_position); |
| 237 | report_util_axis_values(print_position); |
| 238 | serial_write(':'); |
| 239 | print_uint8_base10(sys.probe_succeeded); |
| 240 | report_util_feedback_line_feed(); |
| 241 | } |
| 242 | |
| 243 | |
| 244 | // Prints Grbl NGC parameters (coordinate offsets, probing) |
| 245 | void report_ngc_parameters() |
| 246 | { |
| 247 | float coord_data[N_AXIS]; |
| 248 | uint8_t coord_select; |
| 249 | for (coord_select = 0; coord_select <= SETTING_INDEX_NCOORD; coord_select++) { |
| 250 | if (!(settings_read_coord_data(coord_select,coord_data))) { |
| 251 | report_status_message(STATUS_SETTING_READ_FAIL); |
| 252 | return; |
| 253 | } |
| 254 | printPgmString(PSTR("[G")); |
| 255 | switch (coord_select) { |
| 256 | case 6: printPgmString(PSTR("28")); break; |
| 257 | case 7: printPgmString(PSTR("30")); break; |
| 258 | default: print_uint8_base10(coord_select+54); break; // G54-G59 |
| 259 | } |
| 260 | serial_write(':'); |
| 261 | report_util_axis_values(coord_data); |
| 262 | report_util_feedback_line_feed(); |
| 263 | } |
| 264 | printPgmString(PSTR("[G92:")); // Print G92,G92.1 which are not persistent in memory |
| 265 | report_util_axis_values(gc_state.coord_offset); |
| 266 | report_util_feedback_line_feed(); |
| 267 | printPgmString(PSTR("[TLO:")); // Print tool length offset value |
| 268 | printFloat_CoordValue(gc_state.tool_length_offset); |
| 269 | report_util_feedback_line_feed(); |
| 270 | report_probe_parameters(); // Print probe parameters. Not persistent in memory. |
| 271 | } |
| 272 | |
| 273 | |
| 274 | // Print current gcode parser mode state |
| 275 | void report_gcode_modes() |
| 276 | { |
| 277 | printPgmString(PSTR("[GC:G")); |
| 278 | if (gc_state.modal.motion >= MOTION_MODE_PROBE_TOWARD) { |
| 279 | printPgmString(PSTR("38.")); |
| 280 | print_uint8_base10(gc_state.modal.motion - (MOTION_MODE_PROBE_TOWARD-2)); |
| 281 | } else { |
| 282 | print_uint8_base10(gc_state.modal.motion); |
| 283 | } |
| 284 | |
| 285 | report_util_gcode_modes_G(); |
| 286 | print_uint8_base10(gc_state.modal.coord_select+54); |
| 287 | |
| 288 | report_util_gcode_modes_G(); |
| 289 | print_uint8_base10(gc_state.modal.plane_select+17); |
| 290 | |
| 291 | report_util_gcode_modes_G(); |
| 292 | print_uint8_base10(21-gc_state.modal.units); |
| 293 | |
| 294 | report_util_gcode_modes_G(); |
| 295 | print_uint8_base10(gc_state.modal.distance+90); |
| 296 | |
| 297 | report_util_gcode_modes_G(); |
| 298 | print_uint8_base10(94-gc_state.modal.feed_rate); |
| 299 | |
| 300 | if (gc_state.modal.program_flow) { |
| 301 | report_util_gcode_modes_M(); |
| 302 | switch (gc_state.modal.program_flow) { |
| 303 | case PROGRAM_FLOW_PAUSED : serial_write('0'); break; |
| 304 | // case PROGRAM_FLOW_OPTIONAL_STOP : serial_write('1'); break; // M1 is ignored and not supported. |
| 305 | case PROGRAM_FLOW_COMPLETED_M2 : |
| 306 | case PROGRAM_FLOW_COMPLETED_M30 : |
| 307 | print_uint8_base10(gc_state.modal.program_flow); |
| 308 | break; |
| 309 | } |
| 310 | } |
| 311 | |
| 312 | report_util_gcode_modes_M(); |
| 313 | switch (gc_state.modal.spindle) { |
| 314 | case SPINDLE_ENABLE_CW : serial_write('3'); break; |
| 315 | case SPINDLE_ENABLE_CCW : serial_write('4'); break; |
| 316 | case SPINDLE_DISABLE : serial_write('5'); break; |
| 317 | } |
| 318 | |
| 319 | #ifdef ENABLE_M7 |
| 320 | if (gc_state.modal.coolant) { // Note: Multiple coolant states may be active at the same time. |
| 321 | if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_MIST) { report_util_gcode_modes_M(); serial_write('7'); } |
| 322 | if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_FLOOD) { report_util_gcode_modes_M(); serial_write('8'); } |
| 323 | } else { report_util_gcode_modes_M(); serial_write('9'); } |
| 324 | #else |
| 325 | report_util_gcode_modes_M(); |
| 326 | if (gc_state.modal.coolant) { serial_write('8'); } |
| 327 | else { serial_write('9'); } |
| 328 | #endif |
| 329 | |
| 330 | #ifdef ENABLE_PARKING_OVERRIDE_CONTROL |
| 331 | if (sys.override_ctrl == OVERRIDE_PARKING_MOTION) { |
| 332 | report_util_gcode_modes_M(); |
| 333 | print_uint8_base10(56); |
| 334 | } |
| 335 | #endif |
| 336 | |
| 337 | printPgmString(PSTR(" T")); |
| 338 | print_uint8_base10(gc_state.tool); |
| 339 | |
| 340 | printPgmString(PSTR(" F")); |
| 341 | printFloat_RateValue(gc_state.feed_rate); |
| 342 | |
| 343 | #ifdef VARIABLE_SPINDLE |
| 344 | printPgmString(PSTR(" S")); |
| 345 | printFloat(gc_state.spindle_speed,N_DECIMAL_RPMVALUE); |
| 346 | #endif |
| 347 | |
| 348 | report_util_feedback_line_feed(); |
| 349 | } |
| 350 | |
| 351 | // Prints specified startup line |
| 352 | void report_startup_line(uint8_t n, char *line) |
| 353 | { |
| 354 | printPgmString(PSTR("$N")); |
| 355 | print_uint8_base10(n); |
| 356 | serial_write('='); |
| 357 | printString(line); |
| 358 | report_util_line_feed(); |
| 359 | } |
| 360 | |
| 361 | void report_execute_startup_message(char *line, uint8_t status_code) |
| 362 | { |
| 363 | serial_write('>'); |
| 364 | printString(line); |
| 365 | serial_write(':'); |
| 366 | report_status_message(status_code); |
| 367 | } |
| 368 | |
| 369 | // Prints build info line |
| 370 | void report_build_info(char *line) |
| 371 | { |
| 372 | printPgmString(PSTR("[VER:" GRBL_VERSION "." GRBL_VERSION_BUILD ":")); |
| 373 | printString(line); |
| 374 | report_util_feedback_line_feed(); |
| 375 | printPgmString(PSTR("[OPT:")); // Generate compile-time build option list |
| 376 | #ifdef VARIABLE_SPINDLE |
| 377 | serial_write('V'); |
| 378 | #endif |
| 379 | #ifdef USE_LINE_NUMBERS |
| 380 | serial_write('N'); |
| 381 | #endif |
| 382 | #ifdef ENABLE_M7 |
| 383 | serial_write('M'); |
| 384 | #endif |
| 385 | #ifdef COREXY |
| 386 | serial_write('C'); |
| 387 | #endif |
| 388 | #ifdef PARKING_ENABLE |
| 389 | serial_write('P'); |
| 390 | #endif |
| 391 | #ifdef HOMING_FORCE_SET_ORIGIN |
| 392 | serial_write('Z'); |
| 393 | #endif |
| 394 | #ifdef HOMING_SINGLE_AXIS_COMMANDS |
| 395 | serial_write('H'); |
| 396 | #endif |
| 397 | #ifdef LIMITS_TWO_SWITCHES_ON_AXES |
| 398 | serial_write('T'); |
| 399 | #endif |
| 400 | #ifdef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES |
| 401 | serial_write('A'); |
| 402 | #endif |
| 403 | #ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN |
| 404 | serial_write('D'); |
| 405 | #endif |
| 406 | #ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED |
| 407 | serial_write('0'); |
| 408 | #endif |
| 409 | #ifdef ENABLE_SOFTWARE_DEBOUNCE |
| 410 | serial_write('S'); |
| 411 | #endif |
| 412 | #ifdef ENABLE_PARKING_OVERRIDE_CONTROL |
| 413 | serial_write('R'); |
| 414 | #endif |
| 415 | #ifndef HOMING_INIT_LOCK |
| 416 | serial_write('L'); |
| 417 | #endif |
| 418 | #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN |
| 419 | serial_write('+'); |
| 420 | #endif |
| 421 | #ifndef ENABLE_RESTORE_EEPROM_WIPE_ALL // NOTE: Shown when disabled. |
| 422 | serial_write('*'); |
| 423 | #endif |
| 424 | #ifndef ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS // NOTE: Shown when disabled. |
| 425 | serial_write('$'); |
| 426 | #endif |
| 427 | #ifndef ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS // NOTE: Shown when disabled. |
| 428 | serial_write('#'); |
| 429 | #endif |
| 430 | #ifndef ENABLE_BUILD_INFO_WRITE_COMMAND // NOTE: Shown when disabled. |
| 431 | serial_write('I'); |
| 432 | #endif |
| 433 | #ifndef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE // NOTE: Shown when disabled. |
| 434 | serial_write('E'); |
| 435 | #endif |
| 436 | #ifndef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE // NOTE: Shown when disabled. |
| 437 | serial_write('W'); |
| 438 | #endif |
| 439 | #ifdef ENABLE_DUAL_AXIS |
| 440 | serial_write('2'); |
| 441 | #endif |
| 442 | // NOTE: Compiled values, like override increments/max/min values, may be added at some point later. |
| 443 | serial_write(','); |
| 444 | print_uint8_base10(BLOCK_BUFFER_SIZE-1); |
| 445 | serial_write(','); |
| 446 | print_uint8_base10(RX_BUFFER_SIZE); |
| 447 | |
| 448 | report_util_feedback_line_feed(); |
| 449 | } |
| 450 | |
| 451 | |
| 452 | // Prints the character string line Grbl has received from the user, which has been pre-parsed, |
| 453 | // and has been sent into protocol_execute_line() routine to be executed by Grbl. |
| 454 | void report_echo_line_received(char *line) |
| 455 | { |
| 456 | printPgmString(PSTR("[echo: ")); printString(line); |
| 457 | report_util_feedback_line_feed(); |
| 458 | } |
| 459 | |
| 460 | |
| 461 | // Prints real-time data. This function grabs a real-time snapshot of the stepper subprogram |
| 462 | // and the actual location of the CNC machine. Users may change the following function to their |
| 463 | // specific needs, but the desired real-time data report must be as short as possible. This is |
| 464 | // requires as it minimizes the computational overhead and allows grbl to keep running smoothly, |
| 465 | // especially during g-code programs with fast, short line segments and high frequency reports (5-20Hz). |
| 466 | void report_realtime_status() |
| 467 | { |
| 468 | uint8_t idx; |
| 469 | int32_t current_position[N_AXIS]; // Copy current state of the system position variable |
| 470 | memcpy(current_position,sys_position,sizeof(sys_position)); |
| 471 | float print_position[N_AXIS]; |
| 472 | system_convert_array_steps_to_mpos(print_position,current_position); |
| 473 | |
| 474 | // Report current machine state and sub-states |
| 475 | serial_write('<'); |
| 476 | switch (sys.state) { |
| 477 | case STATE_IDLE: printPgmString(PSTR("Idle")); break; |
| 478 | case STATE_CYCLE: printPgmString(PSTR("Run")); break; |
| 479 | case STATE_HOLD: |
| 480 | if (!(sys.suspend & SUSPEND_JOG_CANCEL)) { |
| 481 | printPgmString(PSTR("Hold:")); |
| 482 | if (sys.suspend & SUSPEND_HOLD_COMPLETE) { serial_write('0'); } // Ready to resume |
| 483 | else { serial_write('1'); } // Actively holding |
| 484 | break; |
| 485 | } // Continues to print jog state during jog cancel. |
| 486 | case STATE_JOG: printPgmString(PSTR("Jog")); break; |
| 487 | case STATE_HOMING: printPgmString(PSTR("Home")); break; |
| 488 | case STATE_ALARM: printPgmString(PSTR("Alarm")); break; |
| 489 | case STATE_CHECK_MODE: printPgmString(PSTR("Check")); break; |
| 490 | case STATE_SAFETY_DOOR: |
| 491 | printPgmString(PSTR("Door:")); |
| 492 | if (sys.suspend & SUSPEND_INITIATE_RESTORE) { |
| 493 | serial_write('3'); // Restoring |
| 494 | } else { |
| 495 | if (sys.suspend & SUSPEND_RETRACT_COMPLETE) { |
| 496 | if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { |
| 497 | serial_write('1'); // Door ajar |
| 498 | } else { |
| 499 | serial_write('0'); |
| 500 | } // Door closed and ready to resume |
| 501 | } else { |
| 502 | serial_write('2'); // Retracting |
| 503 | } |
| 504 | } |
| 505 | break; |
| 506 | case STATE_SLEEP: printPgmString(PSTR("Sleep")); break; |
| 507 | } |
| 508 | |
| 509 | float wco[N_AXIS]; |
| 510 | if (bit_isfalse(settings.status_report_mask,BITFLAG_RT_STATUS_POSITION_TYPE) || |
| 511 | (sys.report_wco_counter == 0) ) { |
| 512 | for (idx=0; idx< N_AXIS; idx++) { |
| 513 | // Apply work coordinate offsets and tool length offset to current position. |
| 514 | wco[idx] = gc_state.coord_system[idx]+gc_state.coord_offset[idx]; |
| 515 | if (idx == TOOL_LENGTH_OFFSET_AXIS) { wco[idx] += gc_state.tool_length_offset; } |
| 516 | if (bit_isfalse(settings.status_report_mask,BITFLAG_RT_STATUS_POSITION_TYPE)) { |
| 517 | print_position[idx] -= wco[idx]; |
| 518 | } |
| 519 | } |
| 520 | } |
| 521 | |
| 522 | // Report machine position |
| 523 | if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_POSITION_TYPE)) { |
| 524 | printPgmString(PSTR("|MPos:")); |
| 525 | } else { |
| 526 | printPgmString(PSTR("|WPos:")); |
| 527 | } |
| 528 | report_util_axis_values(print_position); |
| 529 | |
| 530 | // Returns planner and serial read buffer states. |
| 531 | #ifdef REPORT_FIELD_BUFFER_STATE |
| 532 | if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_BUFFER_STATE)) { |
| 533 | printPgmString(PSTR("|Bf:")); |
| 534 | print_uint8_base10(plan_get_block_buffer_available()); |
| 535 | serial_write(','); |
| 536 | print_uint8_base10(serial_get_rx_buffer_available()); |
| 537 | } |
| 538 | #endif |
| 539 | |
| 540 | #ifdef USE_LINE_NUMBERS |
| 541 | #ifdef REPORT_FIELD_LINE_NUMBERS |
| 542 | // Report current line number |
| 543 | plan_block_t * cur_block = plan_get_current_block(); |
| 544 | if (cur_block != NULL) { |
| 545 | uint32_t ln = cur_block->line_number; |
| 546 | if (ln > 0) { |
| 547 | printPgmString(PSTR("|Ln:")); |
| 548 | printInteger(ln); |
| 549 | } |
| 550 | } |
| 551 | #endif |
| 552 | #endif |
| 553 | |
| 554 | // Report realtime feed speed |
| 555 | #ifdef REPORT_FIELD_CURRENT_FEED_SPEED |
| 556 | #ifdef VARIABLE_SPINDLE |
| 557 | printPgmString(PSTR("|FS:")); |
| 558 | printFloat_RateValue(st_get_realtime_rate()); |
| 559 | serial_write(','); |
| 560 | printFloat(sys.spindle_speed,N_DECIMAL_RPMVALUE); |
| 561 | #else |
| 562 | printPgmString(PSTR("|F:")); |
| 563 | printFloat_RateValue(st_get_realtime_rate()); |
| 564 | #endif |
| 565 | #endif |
| 566 | |
| 567 | #ifdef REPORT_FIELD_PIN_STATE |
| 568 | uint8_t lim_pin_state = limits_get_state(); |
| 569 | uint8_t ctrl_pin_state = system_control_get_state(); |
| 570 | uint8_t prb_pin_state = probe_get_state(); |
| 571 | if (lim_pin_state | ctrl_pin_state | prb_pin_state) { |
| 572 | printPgmString(PSTR("|Pn:")); |
| 573 | if (prb_pin_state) { serial_write('P'); } |
| 574 | if (lim_pin_state) { |
| 575 | #ifdef ENABLE_DUAL_AXIS |
| 576 | #if (DUAL_AXIS_SELECT == X_AXIS) |
| 577 | if (bit_istrue(lim_pin_state,(bit(X_AXIS)|bit(N_AXIS)))) { serial_write('X'); } |
| 578 | if (bit_istrue(lim_pin_state,bit(Y_AXIS))) { serial_write('Y'); } |
| 579 | #endif |
| 580 | #if (DUAL_AXIS_SELECT == Y_AXIS) |
| 581 | if (bit_istrue(lim_pin_state,bit(X_AXIS))) { serial_write('X'); |
| 582 | if (bit_istrue(lim_pin_state,(bit(Y_AXIS)|bit(N_AXIS)))) { serial_write('Y'); } |
| 583 | #endif |
| 584 | if (bit_istrue(lim_pin_state,bit(Z_AXIS))) { serial_write('Z'); } |
| 585 | #else |
| 586 | if (bit_istrue(lim_pin_state,bit(X_AXIS))) { serial_write('X'); } |
| 587 | if (bit_istrue(lim_pin_state,bit(Y_AXIS))) { serial_write('Y'); } |
| 588 | if (bit_istrue(lim_pin_state,bit(Z_AXIS))) { serial_write('Z'); } |
| 589 | #endif |
| 590 | } |
| 591 | if (ctrl_pin_state) { |
| 592 | #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN |
| 593 | if (bit_istrue(ctrl_pin_state,CONTROL_PIN_INDEX_SAFETY_DOOR)) { serial_write('D'); } |
| 594 | #endif |
| 595 | if (bit_istrue(ctrl_pin_state,CONTROL_PIN_INDEX_RESET)) { serial_write('R'); } |
| 596 | if (bit_istrue(ctrl_pin_state,CONTROL_PIN_INDEX_FEED_HOLD)) { serial_write('H'); } |
| 597 | if (bit_istrue(ctrl_pin_state,CONTROL_PIN_INDEX_CYCLE_START)) { serial_write('S'); } |
| 598 | } |
| 599 | } |
| 600 | #endif |
| 601 | |
| 602 | #ifdef REPORT_FIELD_WORK_COORD_OFFSET |
| 603 | if (sys.report_wco_counter > 0) { sys.report_wco_counter--; } |
| 604 | else { |
| 605 | if (sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) { |
| 606 | sys.report_wco_counter = (REPORT_WCO_REFRESH_BUSY_COUNT-1); // Reset counter for slow refresh |
| 607 | } else { sys.report_wco_counter = (REPORT_WCO_REFRESH_IDLE_COUNT-1); } |
| 608 | if (sys.report_ovr_counter == 0) { sys.report_ovr_counter = 1; } // Set override on next report. |
| 609 | printPgmString(PSTR("|WCO:")); |
| 610 | report_util_axis_values(wco); |
| 611 | } |
| 612 | #endif |
| 613 | |
| 614 | #ifdef REPORT_FIELD_OVERRIDES |
| 615 | if (sys.report_ovr_counter > 0) { sys.report_ovr_counter--; } |
| 616 | else { |
| 617 | if (sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) { |
| 618 | sys.report_ovr_counter = (REPORT_OVR_REFRESH_BUSY_COUNT-1); // Reset counter for slow refresh |
| 619 | } else { sys.report_ovr_counter = (REPORT_OVR_REFRESH_IDLE_COUNT-1); } |
| 620 | printPgmString(PSTR("|Ov:")); |
| 621 | print_uint8_base10(sys.f_override); |
| 622 | serial_write(','); |
| 623 | print_uint8_base10(sys.r_override); |
| 624 | serial_write(','); |
| 625 | print_uint8_base10(sys.spindle_speed_ovr); |
| 626 | |
| 627 | uint8_t sp_state = spindle_get_state(); |
| 628 | uint8_t cl_state = coolant_get_state(); |
| 629 | if (sp_state || cl_state) { |
| 630 | printPgmString(PSTR("|A:")); |
| 631 | if (sp_state) { // != SPINDLE_STATE_DISABLE |
| 632 | #ifdef VARIABLE_SPINDLE |
| 633 | #ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN |
| 634 | serial_write('S'); // CW |
| 635 | #else |
| 636 | if (sp_state == SPINDLE_STATE_CW) { serial_write('S'); } // CW |
| 637 | else { serial_write('C'); } // CCW |
| 638 | #endif |
| 639 | #else |
| 640 | if (sp_state & SPINDLE_STATE_CW) { serial_write('S'); } // CW |
| 641 | else { serial_write('C'); } // CCW |
| 642 | #endif |
| 643 | } |
| 644 | if (cl_state & COOLANT_STATE_FLOOD) { serial_write('F'); } |
| 645 | #ifdef ENABLE_M7 |
| 646 | if (cl_state & COOLANT_STATE_MIST) { serial_write('M'); } |
| 647 | #endif |
| 648 | } |
| 649 | } |
| 650 | #endif |
| 651 | |
| 652 | serial_write('>'); |
| 653 | report_util_line_feed(); |
| 654 | } |
| 655 | |
| 656 | |
| 657 | #ifdef DEBUG |
| 658 | void report_realtime_debug() |
| 659 | { |
| 660 | |
| 661 | } |
| 662 | #endif |