diff --git a/Marlin/M100_Free_Mem_Chk.cpp b/Marlin/M100_Free_Mem_Chk.cpp index 5387a71ede..ccbc1c8b0f 100644 --- a/Marlin/M100_Free_Mem_Chk.cpp +++ b/Marlin/M100_Free_Mem_Chk.cpp @@ -40,8 +40,8 @@ * * Also, there are two support functions that can be called from a developer's C code. * - * uint16_t check_for_free_memory_corruption(char * const ptr); - * void M100_dump_routine( char *title, char *start, char *end); + * uint16_t check_for_free_memory_corruption(const char * const ptr); + * void M100_dump_routine(const char * const title, const char *start, const char *end); * * Initial version by Roxy-3D */ @@ -68,7 +68,7 @@ extern char __bss_end; // #define END_OF_HEAP() (__brkval ? __brkval : &__bss_end) -int check_for_free_memory_corruption(char *title); +int check_for_free_memory_corruption(const char * const title); // Location of a variable on its stack frame. Returns a value above // the stack (once the function returns to the caller). @@ -86,7 +86,6 @@ int16_t count_test_bytes(const uint8_t * const ptr) { return -1; } - // // M100 sub-commands // @@ -101,7 +100,7 @@ int16_t count_test_bytes(const uint8_t * const ptr) { * the block. If so, it may indicate memory corruption due to a bad pointer. * Unexpected bytes are flagged in the right column. */ - void dump_free_memory(uint8_t *ptr, uint8_t *sp) { + void dump_free_memory(const uint8_t *ptr, const uint8_t *sp) { // // Start and end the dump on a nice 16 byte boundary // (even though the values are not 16-byte aligned). @@ -121,17 +120,13 @@ int16_t count_test_bytes(const uint8_t * const ptr) { safe_delay(25); SERIAL_CHAR('|'); // Point out non test bytes for (uint8_t i = 0; i < 16; i++) { - char ccc; - ccc = (char) ptr[i]; - if ( &ptr[i]>=&command_queue[0][0] && &ptr[i]<&command_queue[BUFSIZE][MAX_CMD_SIZE]) { // Print out ASCII in the command - if ( ccc<' ' || ccc>0x7e) // buffer area - ccc = ' '; - } - else - if (ccc != TEST_BYTE) // If not display data in the command buffer - ccc = '?'; // area, we flag bytes that don't match the test byte - else - ccc = ' '; + char ccc = (char)ptr[i]; // cast to char before automatically casting to char on assignment, in case the compiler is broken + if (&ptr[i] >= command_queue && &ptr[i] < &command_queue[BUFSIZE][MAX_CMD_SIZE]) { // Print out ASCII in the command buffer area + if (!WITHIN(ccc, ' ', 0x7E)) ccc = ' '; + } + else { // If not in the command buffer area, flag bytes that don't match the test byte + ccc = (ccc == TEST_BYTE) ? ' ' : '?'; + } SERIAL_CHAR(ccc); } SERIAL_EOL; @@ -141,19 +136,16 @@ int16_t count_test_bytes(const uint8_t * const ptr) { } } -void M100_dump_routine( char *title, char *start, char *end) { -unsigned char c; -int i; - -// -// Round the start and end locations to produce full lines of output -// - start = (char*) ((uint16_t) start & 0xfff0); - end = (char*) ((uint16_t) end | 0x000f); - - SERIAL_ECHOLN(title); - dump_free_memory( start, end ); +void M100_dump_routine(const char * const title, const char *start, const char *end) { + SERIAL_ECHOLN(title); + // + // Round the start and end locations to produce full lines of output + // + start = (char*)((uint16_t) start & 0xfff0); + end = (char*)((uint16_t) end | 0x000f); + dump_free_memory(start, end); } + #endif // M100_FREE_MEMORY_DUMPER /** @@ -172,7 +164,7 @@ void free_memory_pool_report(const char * const ptr, const uint16_t size) { const uint16_t j = count_test_bytes(addr); if (j > 8) { SERIAL_ECHOPAIR("Found ", j); - SERIAL_ECHOLNPAIR(" bytes free at 0x", hex_word((uint16_t)addr)); + SERIAL_ECHOLNPAIR(" bytes free at ", hex_address(addr)); if (j > max_cnt) { max_cnt = j; max_addr = addr; @@ -185,7 +177,7 @@ void free_memory_pool_report(const char * const ptr, const uint16_t size) { if (block_cnt > 1) { SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area."); SERIAL_ECHOPAIR("\nLargest free block is ", max_cnt); - SERIAL_ECHOLNPAIR(" bytes at 0x", hex_word((uint16_t)max_addr)); + SERIAL_ECHOLNPAIR(" bytes at ", hex_address(max_addr)); } SERIAL_ECHOLNPAIR("check_for_free_memory_corruption() = ", check_for_free_memory_corruption("M100 F ")); } @@ -206,7 +198,7 @@ void free_memory_pool_report(const char * const ptr, const uint16_t size) { for (uint16_t i = 1; i <= size; i++) { char * const addr = ptr + i * j; *addr = i; - SERIAL_ECHOPAIR("\nCorrupting address: 0x", hex_word((uint16_t)addr)); + SERIAL_ECHOPAIR("\nCorrupting address: ", hex_address(addr)); } SERIAL_EOL; } @@ -234,9 +226,10 @@ void init_free_memory(uint8_t *ptr, int16_t size) { SERIAL_ECHOLNPGM(" bytes of memory initialized.\n"); for (uint16_t i = 0; i < size; i++) { - if (((char) ptr[i]) != TEST_BYTE) { - SERIAL_ECHOPAIR("? address : 0x", hex_word((uint16_t)ptr + i)); + if ((char)ptr[i] != TEST_BYTE) { + SERIAL_ECHOPAIR("? address : ", hex_address(ptr + i)); SERIAL_ECHOLNPAIR("=", hex_byte(ptr[i])); + SERIAL_EOL; } } } @@ -245,13 +238,13 @@ void init_free_memory(uint8_t *ptr, int16_t size) { * M100: Free Memory Check */ void gcode_M100() { - SERIAL_ECHOPAIR("\n__brkval : 0x", hex_word((uint16_t)__brkval)); - SERIAL_ECHOPAIR("\n__bss_end: 0x", hex_word((uint16_t)&__bss_end)); + SERIAL_ECHOPAIR("\n__brkval : ", hex_address(__brkval)); + SERIAL_ECHOPAIR("\n__bss_end : ", hex_address(&__bss_end)); uint8_t *ptr = END_OF_HEAP(), *sp = top_of_stack(); - SERIAL_ECHOPAIR("\nstart of free space : 0x", hex_word((uint16_t)ptr)); - SERIAL_ECHOLNPAIR("\nStack Pointer : 0x", hex_word((uint16_t)sp)); + SERIAL_ECHOPAIR("\nstart of free space : ", hex_address(ptr)); + SERIAL_ECHOLNPAIR("\nStack Pointer : ", hex_address(sp)); // Always init on the first invocation of M100 static bool m100_not_initialized = true; @@ -276,68 +269,66 @@ void gcode_M100() { #endif } -int check_for_free_memory_corruption(char *title) { - char *sp, *ptr; - int block_cnt = 0, i, j, n; +int check_for_free_memory_corruption(const char * const title) { + SERIAL_ECHO(title); - SERIAL_ECHO(title); + char *ptr = END_OF_HEAP(), *sp = top_of_stack(); + int n = sp - ptr; - ptr = __brkval ? __brkval : &__bss_end; - sp = top_of_stack(); + SERIAL_ECHOPAIR("\nfmc() n=", n); + SERIAL_ECHOPAIR("\n&__brkval: ", hex_address(&__brkval)); + SERIAL_ECHOPAIR("=", hex_address(__brkval)); + SERIAL_ECHOPAIR("\n__bss_end: ", hex_address(&__bss_end)); + SERIAL_ECHOPAIR(" sp=", hex_address(sp)); - n = sp - ptr; - SERIAL_ECHOPAIR("\nfmc() n=", n); - SERIAL_ECHOPAIR("\n&__brkval: 0x", hex_word((uint16_t)&__brkval)); - SERIAL_ECHOPAIR("=0x", hex_word((uint16_t)__brkval)); - SERIAL_ECHOPAIR("\n__bss_end: 0x", hex_word((uint16_t)&__bss_end)); - SERIAL_ECHOPAIR(" sp=", hex_word(sp)); + if (sp < ptr) { + SERIAL_ECHOPGM(" sp < Heap "); + // SET_INPUT_PULLUP(63); // if the developer has a switch wired up to their controller board + // safe_delay(5); // this code can be enabled to pause the display as soon as the + // while ( READ(63)) // malfunction is detected. It is currently defaulting to a switch + // idle(); // being on pin-63 which is unassigend and available on most controller + // safe_delay(20); // boards. + // while ( !READ(63)) + // idle(); + safe_delay(20); + #ifdef M100_FREE_MEMORY_DUMPER + M100_dump_routine(" Memory corruption detected with sp 8) { -// SERIAL_ECHOPAIR("Found ", j); -// SERIAL_ECHOLNPAIR(" bytes free at 0x", hex_word((uint16_t)(ptr + i))); - - i += j; - block_cnt++; - SERIAL_ECHOPAIR(" (", block_cnt); - SERIAL_ECHOPAIR(") found=", j); - SERIAL_ECHOPGM(" "); - } + // Scan through the range looking for the biggest block of 0xE5's we can find + int block_cnt = 0; + for (int i = 0; i < n; i++) { + if (ptr[i] == TEST_BYTE) { + int16_t j = count_test_bytes(ptr + i); + if (j > 8) { + // SERIAL_ECHOPAIR("Found ", j); + // SERIAL_ECHOLNPAIR(" bytes free at ", hex_address(ptr + i)); + i += j; + block_cnt++; + SERIAL_ECHOPAIR(" (", block_cnt); + SERIAL_ECHOPAIR(") found=", j); + SERIAL_ECHOPGM(" "); } } - SERIAL_ECHOPAIR(" block_found=", block_cnt); - - if ((block_cnt!=1) || (__brkval != 0x0000)) - SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area."); - - if ((block_cnt==0)) // Make sure the special case of no free blocks shows up as an - block_cnt = -1; // error to the calling code! - - if (block_cnt==1) { - SERIAL_ECHOPGM(" return=0\n"); // if the block_cnt is 1, nothing has broken up the free memory - return 0; // area and it is appropriate to say 'no corruption'. - } - SERIAL_ECHOPGM(" return=true\n"); - return block_cnt; } + SERIAL_ECHOPAIR(" block_found=", block_cnt); + + if (block_cnt != 1 || __brkval != 0x0000) + SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area."); + + if (block_cnt == 0) // Make sure the special case of no free blocks shows up as an + block_cnt = -1; // error to the calling code! + + SERIAL_ECHOPGM(" return="); + if (block_cnt == 1) { + SERIAL_CHAR('0'); // if the block_cnt is 1, nothing has broken up the free memory + SERIAL_EOL; // area and it is appropriate to say 'no corruption'. + return 0; + } + SERIAL_ECHOLNPGM("true"); + return block_cnt; +} #endif // M100_FREE_MEMORY_WATCHER diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index a1b0302193..4f6b31a703 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -284,7 +284,7 @@ #if ENABLED(M100_FREE_MEMORY_WATCHER) void gcode_M100(); - void M100_dump_routine( char *title, char *start, char *end); + void M100_dump_routine(const char * const title, const char *start, const char *end); #endif #if ENABLED(SDSUPPORT) @@ -1091,7 +1091,7 @@ inline void get_serial_commands() { if (IsStopped()) { char* gpos = strchr(command, 'G'); if (gpos) { - int codenum = strtol(gpos + 1, NULL, 10); + const int codenum = strtol(gpos + 1, NULL, 10); switch (codenum) { case 0: case 1: @@ -4167,17 +4167,25 @@ inline void gcode_G28() { #define ABL_VAR #endif - ABL_VAR int verbose_level, abl_probe_index; + ABL_VAR int verbose_level; ABL_VAR float xProbe, yProbe, measured_z; ABL_VAR bool dryrun, abl_should_enable; + #if ENABLED(PROBE_MANUALLY) || ENABLED(AUTO_BED_LEVELING_LINEAR) + ABL_VAR int abl_probe_index; + #endif + #if HAS_SOFTWARE_ENDSTOPS ABL_VAR bool enable_soft_endstops = true; #endif #if ABL_GRID - ABL_VAR uint8_t PR_OUTER_VAR; - ABL_VAR int8_t PR_INNER_VAR; + + #if ENABLED(PROBE_MANUALLY) + ABL_VAR uint8_t PR_OUTER_VAR; + ABL_VAR int8_t PR_INNER_VAR; + #endif + ABL_VAR int left_probe_bed_position, right_probe_bed_position, front_probe_bed_position, back_probe_bed_position; ABL_VAR float xGridSpacing, yGridSpacing; @@ -4186,13 +4194,18 @@ inline void gcode_G28() { #if ABL_PLANAR ABL_VAR uint8_t abl_grid_points_x = GRID_MAX_POINTS_X, abl_grid_points_y = GRID_MAX_POINTS_Y; - ABL_VAR int abl2; ABL_VAR bool do_topography_map; #else // 3-point uint8_t constexpr abl_grid_points_x = GRID_MAX_POINTS_X, abl_grid_points_y = GRID_MAX_POINTS_Y; + #endif - int constexpr abl2 = ABL_GRID_MAX; + #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(PROBE_MANUALLY) + #if ABL_PLANAR + ABL_VAR int abl2; + #else // 3-point + int constexpr abl2 = ABL_GRID_MAX; + #endif #endif #if ENABLED(AUTO_BED_LEVELING_BILINEAR) @@ -4224,7 +4237,10 @@ inline void gcode_G28() { */ if (!g29_in_progress) { - abl_probe_index = 0; + #if ENABLED(PROBE_MANUALLY) || ENABLED(AUTO_BED_LEVELING_LINEAR) + abl_probe_index = 0; + #endif + abl_should_enable = planner.abl_enabled; #if ENABLED(AUTO_BED_LEVELING_BILINEAR) @@ -4284,7 +4300,7 @@ inline void gcode_G28() { return; } - dryrun = code_seen('D') ? code_value_bool() : false; + dryrun = code_seen('D') && code_value_bool(); #if ENABLED(AUTO_BED_LEVELING_LINEAR) @@ -4455,7 +4471,7 @@ inline void gcode_G28() { g29_in_progress = true; if (abl_probe_index == 0) { - // For the initial G29 S2 save software endstop state + // For the initial G29 save software endstop state #if HAS_SOFTWARE_ENDSTOPS enable_soft_endstops = soft_endstops_enabled; #endif @@ -4586,7 +4602,6 @@ inline void gcode_G28() { #else // !PROBE_MANUALLY - bool stow_probe_after_each = code_seen('E'); #if ABL_GRID @@ -4927,14 +4942,12 @@ inline void gcode_G28() { * S = Stows the probe if 1 (default=1) */ inline void gcode_G30() { - float X_probe_location = code_seen('X') ? code_value_linear_units() : current_position[X_AXIS] + X_PROBE_OFFSET_FROM_EXTRUDER, - Y_probe_location = code_seen('Y') ? code_value_linear_units() : current_position[Y_AXIS] + Y_PROBE_OFFSET_FROM_EXTRUDER; + const float xpos = code_seen('X') ? code_value_linear_units() : current_position[X_AXIS] + X_PROBE_OFFSET_FROM_EXTRUDER, + ypos = code_seen('Y') ? code_value_linear_units() : current_position[Y_AXIS] + Y_PROBE_OFFSET_FROM_EXTRUDER, + pos[XYZ] = { xpos, ypos, LOGICAL_Z_POSITION(0) }; - float pos[XYZ] = { X_probe_location, Y_probe_location, LOGICAL_Z_POSITION(0) }; if (!position_is_reachable(pos, true)) return; - bool stow = code_seen('S') ? code_value_bool() : true; - // Disable leveling so the planner won't mess with us #if PLANNER_LEVELING set_bed_leveling_enabled(false); @@ -4942,14 +4955,11 @@ inline void gcode_G28() { setup_for_endstop_or_probe_move(); - float measured_z = probe_pt(X_probe_location, Y_probe_location, stow, 1); + const float measured_z = probe_pt(xpos, ypos, !code_seen('S') || code_value_bool(), 1); - SERIAL_PROTOCOLPGM("Bed X: "); - SERIAL_PROTOCOL(FIXFLOAT(X_probe_location)); - SERIAL_PROTOCOLPGM(" Y: "); - SERIAL_PROTOCOL(FIXFLOAT(Y_probe_location)); - SERIAL_PROTOCOLPGM(" Z: "); - SERIAL_PROTOCOLLN(FIXFLOAT(measured_z)); + SERIAL_PROTOCOLPAIR("Bed X: ", FIXFLOAT(xpos)); + SERIAL_PROTOCOLPAIR(" Y: ", FIXFLOAT(ypos)); + SERIAL_PROTOCOLLNPAIR(" Z: ", FIXFLOAT(measured_z)); clean_up_after_endstop_or_probe_move(); @@ -5466,7 +5476,7 @@ inline void gcode_G92() { * M1: Conditional stop - Wait for user button press on LCD */ inline void gcode_M0_M1() { - char* args = current_command_args; + const char * const args = current_command_args; millis_t codenum = 0; bool hasP = false, hasS = false; @@ -5524,7 +5534,7 @@ inline void gcode_G92() { KEEPALIVE_STATE(IN_HANDLER); } -#endif // EMERGENCY_PARSER || ULTIPANEL +#endif // HAS_RESUME_CONTINUE /** * M17: Enable power on all stepper motors @@ -5806,70 +5816,94 @@ inline void gcode_M42() { #include "pinsDebug.h" inline void toggle_pins() { - int pin, j; + const bool I_flag = code_seen('I') && code_value_bool(); + const int repeat = code_seen('R') ? code_value_int() : 1, + start = code_seen('S') ? code_value_int() : 0, + end = code_seen('E') ? code_value_int() : NUM_DIGITAL_PINS - 1, + wait = code_seen('W') ? code_value_int() : 500; - bool I_flag = code_seen('I') ? code_value_bool() : false; - - int repeat = code_seen('R') ? code_value_int() : 1, - start = code_seen('S') ? code_value_int() : 0, - end = code_seen('E') ? code_value_int() : NUM_DIGITAL_PINS - 1, - wait = code_seen('W') ? code_value_int() : 500; - - for (pin = start; pin <= end; pin++) { - if (!I_flag && pin_is_protected(pin)) { - SERIAL_ECHOPAIR("Sensitive Pin: ", pin); - SERIAL_ECHOPGM(" untouched.\n"); + for (uint8_t pin = start; pin <= end; pin++) { + if (!I_flag && pin_is_protected(pin)) { + SERIAL_ECHOPAIR("Sensitive Pin: ", pin); + SERIAL_ECHOLNPGM(" untouched."); + } + else { + SERIAL_ECHOPAIR("Pulsing Pin: ", pin); + pinMode(pin, OUTPUT); + for (int16_t j = 0; j < repeat; j++) { + digitalWrite(pin, 0); + safe_delay(wait); + digitalWrite(pin, 1); + safe_delay(wait); + digitalWrite(pin, 0); + safe_delay(wait); } - else { - SERIAL_ECHOPAIR("Pulsing Pin: ", pin); - pinMode(pin, OUTPUT); - for(j = 0; j < repeat; j++) { - digitalWrite(pin, 0); - safe_delay(wait); - digitalWrite(pin, 1); - safe_delay(wait); - digitalWrite(pin, 0); - safe_delay(wait); - } - } - SERIAL_ECHOPGM("\n"); + } + SERIAL_CHAR('\n'); } - SERIAL_ECHOPGM("Done\n"); + SERIAL_ECHOLNPGM("Done."); + } // toggle_pins - inline void servo_probe_test(){ - #if !(NUM_SERVOS >= 1 && HAS_SERVO_0) + inline void servo_probe_test() { + #if !(NUM_SERVOS > 0 && HAS_SERVO_0) + SERIAL_ERROR_START; SERIAL_ERRORLNPGM("SERVO not setup"); + #elif !HAS_Z_SERVO_ENDSTOP + SERIAL_ERROR_START; SERIAL_ERRORLNPGM("Z_ENDSTOP_SERVO_NR not setup"); + #else - uint8_t probe_index = code_seen('P') ? code_value_byte() : Z_ENDSTOP_SERVO_NR; + + #if !defined(z_servo_angle) + const int z_servo_angle[2] = Z_SERVO_ANGLES; + #endif + + const uint8_t probe_index = code_seen('P') ? code_value_byte() : Z_ENDSTOP_SERVO_NR; + SERIAL_PROTOCOLLNPGM("Servo probe test"); SERIAL_PROTOCOLLNPAIR(". using index: ", probe_index); SERIAL_PROTOCOLLNPAIR(". deploy angle: ", z_servo_angle[0]); SERIAL_PROTOCOLLNPAIR(". stow angle: ", z_servo_angle[1]); + bool probe_inverting; + #if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) + #define PROBE_TEST_PIN Z_MIN_PIN + SERIAL_PROTOCOLLNPAIR(". probe uses Z_MIN pin: ", PROBE_TEST_PIN); SERIAL_PROTOCOLLNPGM(". uses Z_MIN_ENDSTOP_INVERTING (ignores Z_MIN_PROBE_ENDSTOP_INVERTING)"); SERIAL_PROTOCOLPGM(". Z_MIN_ENDSTOP_INVERTING: "); - if (Z_MIN_ENDSTOP_INVERTING) SERIAL_PROTOCOLLNPGM("true"); - else SERIAL_PROTOCOLLNPGM("false"); + + #if Z_MIN_ENDSTOP_INVERTING + SERIAL_PROTOCOLLNPGM("true"); + #else + SERIAL_PROTOCOLLNPGM("false"); + #endif + probe_inverting = Z_MIN_ENDSTOP_INVERTING; + #elif ENABLED(Z_MIN_PROBE_ENDSTOP) + #define PROBE_TEST_PIN Z_MIN_PROBE_PIN SERIAL_PROTOCOLLNPAIR(". probe uses Z_MIN_PROBE_PIN: ", PROBE_TEST_PIN); SERIAL_PROTOCOLLNPGM(". uses Z_MIN_PROBE_ENDSTOP_INVERTING (ignores Z_MIN_ENDSTOP_INVERTING)"); SERIAL_PROTOCOLPGM(". Z_MIN_PROBE_ENDSTOP_INVERTING: "); - if (Z_MIN_PROBE_ENDSTOP_INVERTING) SERIAL_PROTOCOLLNPGM("true"); - else SERIAL_PROTOCOLLNPGM("false"); + + #if Z_MIN_PROBE_ENDSTOP_INVERTING + SERIAL_PROTOCOLLNPGM("true"); + #else + SERIAL_PROTOCOLLNPGM("false"); + #endif + probe_inverting = Z_MIN_PROBE_ENDSTOP_INVERTING; - #else - #error "ERROR - probe pin not defined - strange, SANITY_CHECK should have caught this" + #endif + SERIAL_PROTOCOLLNPGM(". deploy & stow 4 times"); pinMode(PROBE_TEST_PIN, INPUT_PULLUP); bool deploy_state; @@ -5883,7 +5917,9 @@ inline void gcode_M42() { stow_state = digitalRead(PROBE_TEST_PIN); } if (probe_inverting != deploy_state) SERIAL_PROTOCOLLNPGM("WARNING - INVERTING setting probably backwards"); + refresh_cmd_timeout(); + if (deploy_state != stow_state) { SERIAL_PROTOCOLLNPGM("BLTouch clone detected"); if (deploy_state) { @@ -5900,32 +5936,43 @@ inline void gcode_M42() { } else { // measure active signal length - servo[probe_index].move(z_servo_angle[0]); //deploy + servo[probe_index].move(z_servo_angle[0]); // deploy safe_delay(500); SERIAL_PROTOCOLLNPGM("please trigger probe"); uint16_t probe_counter = 0; - for (uint16_t j = 0; j < 500*30 && probe_counter == 0 ; j++) { // allow 30 seconds max for operator to trigger probe + + // Allow 30 seconds max for operator to trigger probe + for (uint16_t j = 0; j < 500 * 30 && probe_counter == 0 ; j++) { + safe_delay(2); - if ( 0 == j%(500*1)) {refresh_cmd_timeout(); watchdog_reset();} // beat the dog every 45 seconds - if (deploy_state != digitalRead(PROBE_TEST_PIN)) { // probe triggered - for (probe_counter = 1; probe_counter < 50 && (deploy_state != digitalRead(PROBE_TEST_PIN)); probe_counter ++) { + + if (0 == j % (500 * 1)) // keep cmd_timeout happy + refresh_cmd_timeout(); + + if (deploy_state != digitalRead(PROBE_TEST_PIN)) { // probe triggered + + for (probe_counter = 1; probe_counter < 50 && deploy_state != digitalRead(PROBE_TEST_PIN); ++probe_counter) safe_delay(2); - } - if (probe_counter == 50) { - SERIAL_PROTOCOLLNPGM("Z Servo Probe detected"); // >= 100mS active time - } - else if (probe_counter >= 2 ) { - SERIAL_PROTOCOLLNPAIR("BLTouch compatible probe detected - pulse width (+/- 4mS): ", probe_counter * 2 ); // allow 4 - 100mS pulse - } - else { - SERIAL_PROTOCOLLNPGM("noise detected - please re-run test"); // less than 2mS pulse - } + + if (probe_counter == 50) + SERIAL_PROTOCOLLNPGM("Z Servo Probe detected"); // >= 100mS active time + else if (probe_counter >= 2) + SERIAL_PROTOCOLLNPAIR("BLTouch compatible probe detected - pulse width (+/- 4mS): ", probe_counter * 2); // allow 4 - 100mS pulse + else + SERIAL_PROTOCOLLNPGM("noise detected - please re-run test"); // less than 2mS pulse + servo[probe_index].move(z_servo_angle[1]); //stow + } // pulse detected - } // for loop waiting for trigger + + } // for loop waiting for trigger + if (probe_counter == 0) SERIAL_PROTOCOLLNPGM("trigger not detected"); - } // measure active signal length + + } // measure active signal length + #endif + } // servo_probe_test /** @@ -5977,39 +6024,43 @@ inline void gcode_M42() { } // Get the range of pins to test or watch - int first_pin = 0, last_pin = NUM_DIGITAL_PINS - 1; - if (code_seen('P')) { - first_pin = last_pin = code_value_byte(); - if (first_pin > NUM_DIGITAL_PINS - 1) return; - } + const uint8_t first_pin = code_seen('P') ? code_value_byte() : 0, + last_pin = code_seen('P') ? first_pin : NUM_DIGITAL_PINS - 1; - bool ignore_protection = code_seen('I') ? code_value_bool() : false; + if (first_pin > last_pin) return; + + const bool ignore_protection = code_seen('I') && code_value_bool(); // Watch until click, M108, or reset - if (code_seen('W') && code_value_bool()) { // watch digital pins + if (code_seen('W') && code_value_bool()) { SERIAL_PROTOCOLLNPGM("Watching pins"); byte pin_state[last_pin - first_pin + 1]; for (int8_t pin = first_pin; pin <= last_pin; pin++) { if (pin_is_protected(pin) && !ignore_protection) continue; pinMode(pin, INPUT_PULLUP); - // if (IS_ANALOG(pin)) - // pin_state[pin - first_pin] = analogRead(pin - analogInputToDigitalPin(0)); // int16_t pin_state[...] - // else - pin_state[pin - first_pin] = digitalRead(pin); + /* + if (IS_ANALOG(pin)) + pin_state[pin - first_pin] = analogRead(pin - analogInputToDigitalPin(0)); // int16_t pin_state[...] + else + //*/ + pin_state[pin - first_pin] = digitalRead(pin); } #if HAS_RESUME_CONTINUE wait_for_user = true; + KEEPALIVE_STATE(PAUSED_FOR_USER); #endif - for(;;) { + for (;;) { for (int8_t pin = first_pin; pin <= last_pin; pin++) { if (pin_is_protected(pin)) continue; - byte val; - // if (IS_ANALOG(pin)) - // val = analogRead(pin - analogInputToDigitalPin(0)); // int16_t val - // else - val = digitalRead(pin); + const byte val = + /* + IS_ANALOG(pin) + ? analogRead(pin - analogInputToDigitalPin(0)) : // int16_t val + : + //*/ + digitalRead(pin); if (val != pin_state[pin - first_pin]) { report_pin_state(pin); pin_state[pin - first_pin] = val; @@ -6017,7 +6068,10 @@ inline void gcode_M42() { } #if HAS_RESUME_CONTINUE - if (!wait_for_user) break; + if (!wait_for_user) { + KEEPALIVE_STATE(IN_HANDLER); + break; + } #endif safe_delay(500); @@ -9571,8 +9625,8 @@ void process_next_command() { SERIAL_ECHO_START; SERIAL_ECHOLN(current_command); #if ENABLED(M100_FREE_MEMORY_WATCHER) - SERIAL_ECHOPAIR("slot:", cmd_queue_index_r); - M100_dump_routine( " Command Queue:", &command_queue[0][0], &command_queue[BUFSIZE][MAX_CMD_SIZE] ); + SERIAL_ECHOPAIR("slot:", cmd_queue_index_r); + M100_dump_routine(" Command Queue:", &command_queue[0][0], &command_queue[BUFSIZE][MAX_CMD_SIZE]); #endif } @@ -11166,19 +11220,20 @@ void prepare_move_to_destination() { */ void plan_arc( float logical[XYZE], // Destination position - float* offset, // Center of rotation relative to current_position - uint8_t clockwise // Clockwise? + float *offset, // Center of rotation relative to current_position + uint8_t clockwise // Clockwise? ) { - float radius = HYPOT(offset[X_AXIS], offset[Y_AXIS]), - center_X = current_position[X_AXIS] + offset[X_AXIS], - center_Y = current_position[Y_AXIS] + offset[Y_AXIS], - linear_travel = logical[Z_AXIS] - current_position[Z_AXIS], - extruder_travel = logical[E_AXIS] - current_position[E_AXIS], - r_X = -offset[X_AXIS], // Radius vector from center to current location - r_Y = -offset[Y_AXIS], - rt_X = logical[X_AXIS] - center_X, - rt_Y = logical[Y_AXIS] - center_Y; + float r_X = -offset[X_AXIS], // Radius vector from center to current location + r_Y = -offset[Y_AXIS]; + + const float radius = HYPOT(r_X, r_Y), + center_X = current_position[X_AXIS] - r_X, + center_Y = current_position[Y_AXIS] - r_Y, + rt_X = logical[X_AXIS] - center_X, + rt_Y = logical[Y_AXIS] - center_Y, + linear_travel = logical[Z_AXIS] - current_position[Z_AXIS], + extruder_travel = logical[E_AXIS] - current_position[E_AXIS]; // CCW angle of rotation between position and target from the circle center. Only one atan2() trig computation required. float angular_travel = atan2(r_X * rt_Y - r_Y * rt_X, r_X * rt_X + r_Y * rt_Y); @@ -11222,12 +11277,12 @@ void prepare_move_to_destination() { * This is important when there are successive arc motions. */ // Vector rotation matrix values - float arc_target[XYZE], - theta_per_segment = angular_travel / segments, - linear_per_segment = linear_travel / segments, - extruder_per_segment = extruder_travel / segments, - sin_T = theta_per_segment, - cos_T = 1 - 0.5 * sq(theta_per_segment); // Small angle approximation + float arc_target[XYZE]; + const float theta_per_segment = angular_travel / segments, + linear_per_segment = linear_travel / segments, + extruder_per_segment = extruder_travel / segments, + sin_T = theta_per_segment, + cos_T = 1 - 0.5 * sq(theta_per_segment); // Small angle approximation // Initialize the linear axis arc_target[Z_AXIS] = current_position[Z_AXIS]; @@ -11235,7 +11290,7 @@ void prepare_move_to_destination() { // Initialize the extruder axis arc_target[E_AXIS] = current_position[E_AXIS]; - float fr_mm_s = MMS_SCALED(feedrate_mm_s); + const float fr_mm_s = MMS_SCALED(feedrate_mm_s); millis_t next_idle_ms = millis() + 200UL; @@ -11250,7 +11305,7 @@ void prepare_move_to_destination() { if (++count < N_ARC_CORRECTION) { // Apply vector rotation matrix to previous r_X / 1 - float r_new_Y = r_X * sin_T + r_Y * cos_T; + const float r_new_Y = r_X * sin_T + r_Y * cos_T; r_X = r_X * cos_T - r_Y * sin_T; r_Y = r_new_Y; } @@ -11259,8 +11314,8 @@ void prepare_move_to_destination() { // Compute exact location by applying transformation matrix from initial radius vector(=-offset). // To reduce stuttering, the sin and cos could be computed at different times. // For now, compute both at the same time. - float cos_Ti = cos(i * theta_per_segment), - sin_Ti = sin(i * theta_per_segment); + const float cos_Ti = cos(i * theta_per_segment), + sin_Ti = sin(i * theta_per_segment); r_X = -offset[X_AXIS] * cos_Ti + offset[Y_AXIS] * sin_Ti; r_Y = -offset[X_AXIS] * sin_Ti - offset[Y_AXIS] * cos_Ti; count = 0; @@ -11774,30 +11829,15 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) { enable_E0(); #else // !SWITCHING_EXTRUDER switch (active_extruder) { - case 0: - oldstatus = E0_ENABLE_READ; - enable_E0(); - break; + case 0: oldstatus = E0_ENABLE_READ; enable_E0(); break; #if E_STEPPERS > 1 - case 1: - oldstatus = E1_ENABLE_READ; - enable_E1(); - break; + case 1: oldstatus = E1_ENABLE_READ; enable_E1(); break; #if E_STEPPERS > 2 - case 2: - oldstatus = E2_ENABLE_READ; - enable_E2(); - break; + case 2: oldstatus = E2_ENABLE_READ; enable_E2(); break; #if E_STEPPERS > 3 - case 3: - oldstatus = E3_ENABLE_READ; - enable_E3(); - break; + case 3: oldstatus = E3_ENABLE_READ; enable_E3(); break; #if E_STEPPERS > 4 - case 4: - oldstatus = E4_ENABLE_READ; - enable_E4(); - break; + case 4: oldstatus = E4_ENABLE_READ; enable_E4(); break; #endif // E_STEPPERS > 4 #endif // E_STEPPERS > 3 #endif // E_STEPPERS > 2 @@ -11817,25 +11857,15 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) { E0_ENABLE_WRITE(oldstatus); #else switch (active_extruder) { - case 0: - E0_ENABLE_WRITE(oldstatus); - break; + case 0: E0_ENABLE_WRITE(oldstatus); break; #if E_STEPPERS > 1 - case 1: - E1_ENABLE_WRITE(oldstatus); - break; + case 1: E1_ENABLE_WRITE(oldstatus); break; #if E_STEPPERS > 2 - case 2: - E2_ENABLE_WRITE(oldstatus); - break; + case 2: E2_ENABLE_WRITE(oldstatus); break; #if E_STEPPERS > 3 - case 3: - E3_ENABLE_WRITE(oldstatus); - break; + case 3: E3_ENABLE_WRITE(oldstatus); break; #if E_STEPPERS > 4 - case 4: - E4_ENABLE_WRITE(oldstatus); - break; + case 4: E4_ENABLE_WRITE(oldstatus); break; #endif // E_STEPPERS > 4 #endif // E_STEPPERS > 3 #endif // E_STEPPERS > 2 diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp index cf513c18f2..fb82f23704 100644 --- a/Marlin/configuration_store.cpp +++ b/Marlin/configuration_store.cpp @@ -339,7 +339,10 @@ void MarlinSettings::postprocess() { #if ENABLED(MESH_BED_LEVELING) // Compile time test that sizeof(mbl.z_values) is as expected - typedef char c_assert[(sizeof(mbl.z_values) == (GRID_MAX_POINTS_X) * (GRID_MAX_POINTS_Y) * sizeof(dummy)) ? 1 : -1]; + static_assert( + sizeof(mbl.z_values) == (GRID_MAX_POINTS_X) * (GRID_MAX_POINTS_Y) * sizeof(mbl.z_values[0][0]), + "MBL Z array is the wrong size." + ); const bool leveling_is_on = TEST(mbl.status, MBL_STATUS_HAS_MESH_BIT); const uint8_t mesh_num_x = GRID_MAX_POINTS_X, mesh_num_y = GRID_MAX_POINTS_Y; EEPROM_WRITE(leveling_is_on); @@ -381,7 +384,10 @@ void MarlinSettings::postprocess() { #if ENABLED(AUTO_BED_LEVELING_BILINEAR) // Compile time test that sizeof(bed_level_grid) is as expected - typedef char c_assert[(sizeof(bed_level_grid) == (GRID_MAX_POINTS_X) * (GRID_MAX_POINTS_Y) * sizeof(dummy)) ? 1 : -1]; + static_assert( + sizeof(bed_level_grid) == (GRID_MAX_POINTS_X) * (GRID_MAX_POINTS_Y) * sizeof(bed_level_grid[0][0]), + "Bilinear Z array is the wrong size." + ); const uint8_t grid_max_x = GRID_MAX_POINTS_X, grid_max_y = GRID_MAX_POINTS_Y; EEPROM_WRITE(grid_max_x); // 1 byte EEPROM_WRITE(grid_max_y); // 1 byte diff --git a/Marlin/hex_print_routines.cpp b/Marlin/hex_print_routines.cpp index 02b07754d1..39e5b4cd73 100644 --- a/Marlin/hex_print_routines.cpp +++ b/Marlin/hex_print_routines.cpp @@ -19,32 +19,35 @@ * along with this program. If not, see . * */ - - #include "Marlin.h" #if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(M100_FREE_MEMORY_WATCHER) #include "hex_print_routines.h" -static char _hex[5] = { 0 }; +static char _hex[7] = "0x0000"; char* hex_byte(const uint8_t b) { - _hex[0] = hex_nybble(b >> 4); - _hex[1] = hex_nybble(b); - _hex[2] = '\0'; - return _hex; + _hex[4] = hex_nybble(b >> 4); + _hex[5] = hex_nybble(b); + return &_hex[4]; } char* hex_word(const uint16_t w) { - _hex[0] = hex_nybble(w >> 12); - _hex[1] = hex_nybble(w >> 8); - _hex[2] = hex_nybble(w >> 4); - _hex[3] = hex_nybble(w); + _hex[2] = hex_nybble(w >> 12); + _hex[3] = hex_nybble(w >> 8); + _hex[4] = hex_nybble(w >> 4); + _hex[5] = hex_nybble(w); + return &_hex[2]; +} + +char* hex_address(const void * const w) { + (void)hex_word((uint16_t)w); return _hex; } -void print_hex_nybble(const uint8_t n) { SERIAL_CHAR(hex_nybble(n)); } -void print_hex_byte(const uint8_t b) { SERIAL_ECHO(hex_byte(b)); } -void print_hex_word(const uint16_t w) { SERIAL_ECHO(hex_word(w)); } +void print_hex_nybble(const uint8_t n) { SERIAL_CHAR(hex_nybble(n)); } +void print_hex_byte(const uint8_t b) { SERIAL_ECHO(hex_byte(b)); } +void print_hex_word(const uint16_t w) { SERIAL_ECHO(hex_word(w)); } +void print_hex_address(const void * const w) { SERIAL_ECHO(hex_address(w)); } #endif // AUTO_BED_LEVELING_UBL || M100_FREE_MEMORY_WATCHER diff --git a/Marlin/hex_print_routines.h b/Marlin/hex_print_routines.h index c5c4f759f0..ea40733318 100644 --- a/Marlin/hex_print_routines.h +++ b/Marlin/hex_print_routines.h @@ -36,10 +36,12 @@ inline char hex_nybble(const uint8_t n) { } char* hex_byte(const uint8_t b); char* hex_word(const uint16_t w); +char* hex_address(const void * const w); void print_hex_nybble(const uint8_t n); void print_hex_byte(const uint8_t b); void print_hex_word(const uint16_t w); +void print_hex_address(const void * const w); #endif // AUTO_BED_LEVELING_UBL || M100_FREE_MEMORY_WATCHER #endif // HEX_PRINT_ROUTINES_H diff --git a/Marlin/pinsDebug.h b/Marlin/pinsDebug.h index a60b7449cd..a40d1480df 100644 --- a/Marlin/pinsDebug.h +++ b/Marlin/pinsDebug.h @@ -255,12 +255,11 @@ static void err_is_counter() { SERIAL_PROTOCOLPGM(" non-standard PWM mode"); } static void err_is_interrupt() { - SERIAL_PROTOCOLPGM(" compare interrupt enabled "); + SERIAL_PROTOCOLPGM(" compare interrupt enabled"); } static void err_prob_interrupt() { SERIAL_PROTOCOLPGM(" overflow interrupt enabled"); } -static void can_be_used() { SERIAL_PROTOCOLPGM(" can be used as PWM "); } void com_print(uint8_t N, uint8_t Z) { uint8_t *TCCRA = (uint8_t*) TCCR_A(N); @@ -325,9 +324,6 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm n - } static void pwm_details(uint8_t pin) { - char buffer[20]; // for the sprintf statements - uint8_t WGM; - switch(digitalPinToTimer(pin)) { #if defined(TCCR0A) && defined(COM0A1) @@ -524,7 +520,7 @@ inline void report_pin_state_extended(int8_t pin, bool ignore, bool extended = t SERIAL_PROTOCOLPAIR(" Input = ", digitalRead_mod(pin)); } - //if (!pwm_status(pin)) SERIAL_ECHOCHAR(' '); // add padding if it's not a PWM pin + //if (!pwm_status(pin)) SERIAL_CHAR(' '); // add padding if it's not a PWM pin if (extended) pwm_details(pin); // report PWM capabilities only if doing an extended report SERIAL_EOL; } diff --git a/Marlin/ubl.cpp b/Marlin/ubl.cpp index 1dce269840..056632d24d 100644 --- a/Marlin/ubl.cpp +++ b/Marlin/ubl.cpp @@ -118,7 +118,7 @@ eeprom_read_block((void *)&z_values, (void *)j, sizeof(z_values)); SERIAL_PROTOCOLPAIR("Mesh loaded from slot ", m); - SERIAL_PROTOCOLLNPAIR(" at offset 0x", hex_word(j)); + SERIAL_PROTOCOLLNPAIR(" at offset ", hex_address((void*)j)); } void unified_bed_leveling::store_mesh(const int16_t m) { @@ -140,7 +140,7 @@ eeprom_write_block((const void *)&z_values, (void *)j, sizeof(z_values)); SERIAL_PROTOCOLPAIR("Mesh saved in slot ", m); - SERIAL_PROTOCOLLNPAIR(" at offset 0x", hex_word(j)); + SERIAL_PROTOCOLLNPAIR(" at offset ", hex_address((void*)j)); } void unified_bed_leveling::reset() { diff --git a/Marlin/ubl_G29.cpp b/Marlin/ubl_G29.cpp index f6e2b13ab6..6c4fcd23a7 100644 --- a/Marlin/ubl_G29.cpp +++ b/Marlin/ubl_G29.cpp @@ -35,7 +35,6 @@ #include - void lcd_babystep_z(); void lcd_return_to_status(); bool lcd_clicked(); void lcd_implementation_clear(); @@ -305,7 +304,7 @@ // The simple parameter flags and values are 'static' so parameter parsing can be in a support routine. static int g29_verbose_level, phase_value = -1, repetition_cnt, - storage_slot=0, map_type, grid_size; + storage_slot = 0, map_type, grid_size; static bool repeat_flag, c_flag, x_flag, y_flag; static float x_pos, y_pos, measured_z, card_thickness = 0.0, ubl_constant = 0.0; @@ -330,13 +329,10 @@ // Invalidate Mesh Points. This command is a little bit asymetrical because // it directly specifies the repetition count and does not use the 'R' parameter. if (code_seen('I')) { - int cnt = 0; + uint8_t cnt = 0; repetition_cnt = code_has_value() ? code_value_int() : 1; while (repetition_cnt--) { - if (cnt>20) { - cnt = 0; - idle(); - } + if (cnt > 20) { cnt = 0; idle(); } const mesh_index_pair location = find_closest_mesh_point_of_type(REAL, x_pos, y_pos, 0, NULL, false); // The '0' says we want to use the nozzle's position if (location.x_index < 0) { SERIAL_PROTOCOLLNPGM("Entire Mesh invalidated.\n"); @@ -381,7 +377,7 @@ } if (code_seen('J')) { - if (grid_size<2 || grid_size>5) { + if (!WITHIN(grid_size, 2, 5)) { SERIAL_PROTOCOLLNPGM("ERROR - grid size must be between 2 and 5"); return; } @@ -996,7 +992,7 @@ repetition_cnt = 0; repeat_flag = code_seen('R'); if (repeat_flag) { - repetition_cnt = code_has_value() ? code_value_int() : GRID_MAX_POINTS_X*GRID_MAX_POINTS_Y; + repetition_cnt = code_has_value() ? code_value_int() : (GRID_MAX_POINTS_X) * (GRID_MAX_POINTS_Y); if (repetition_cnt < 1) { SERIAL_PROTOCOLLNPGM("Invalid Repetition count.\n"); return UBL_ERR; @@ -1206,9 +1202,9 @@ SERIAL_PROTOCOLLNPAIR("ubl_state_recursion_chk :", ubl_state_recursion_chk); SERIAL_EOL; safe_delay(50); - SERIAL_PROTOCOLLNPAIR("Free EEPROM space starts at: 0x", hex_word(ubl.eeprom_start)); + SERIAL_PROTOCOLLNPAIR("Free EEPROM space starts at: ", hex_address((void*)ubl.eeprom_start)); - SERIAL_PROTOCOLLNPAIR("end of EEPROM : 0x", hex_word(E2END)); + SERIAL_PROTOCOLLNPAIR("end of EEPROM : ", hex_address((void*)E2END)); safe_delay(50); SERIAL_PROTOCOLLNPAIR("sizeof(ubl) : ", (int)sizeof(ubl)); @@ -1217,7 +1213,7 @@ SERIAL_EOL; safe_delay(50); - SERIAL_PROTOCOLLNPAIR("EEPROM free for UBL: 0x", hex_word(k)); + SERIAL_PROTOCOLLNPAIR("EEPROM free for UBL: ", hex_address((void*)k)); safe_delay(50); SERIAL_PROTOCOLPAIR("EEPROM can hold ", k / sizeof(ubl.z_values)); @@ -1295,7 +1291,7 @@ eeprom_read_block((void *)&tmp_z_values, (void *)j, sizeof(tmp_z_values)); SERIAL_ECHOPAIR("Subtracting Mesh ", storage_slot); - SERIAL_PROTOCOLLNPAIR(" loaded from EEPROM address 0x", hex_word(j)); // Soon, we can remove the extra clutter of printing + SERIAL_PROTOCOLLNPAIR(" loaded from EEPROM address ", hex_address((void*)j)); // Soon, we can remove the extra clutter of printing // the address in the EEPROM where the Mesh is stored. for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)