diff --git a/Firmware/Configuration.h b/Firmware/Configuration.h index 62688ebe..a6c89c88 100644 --- a/Firmware/Configuration.h +++ b/Firmware/Configuration.h @@ -16,8 +16,8 @@ extern uint16_t nPrinterType; extern PGM_P sPrinterName; // Firmware version -#define FW_VERSION "3.9.3" -#define FW_COMMIT_NR 3556 +#define FW_VERSION "3.10.0-RC2" +#define FW_COMMIT_NR 4104 // FW_VERSION_UNKNOWN means this is an unofficial build. // The firmware should only be checked into github with this symbol. #define FW_DEV_VERSION FW_VERSION_UNKNOWN diff --git a/Firmware/Configuration_adv.h b/Firmware/Configuration_adv.h index 75ac0be9..59590b6f 100644 --- a/Firmware/Configuration_adv.h +++ b/Firmware/Configuration_adv.h @@ -387,6 +387,12 @@ const unsigned int dropsegments=5; //everything with less than this number of st */ #define EXTENDED_CAPABILITIES_REPORT +/** + * Enable M120/M121 G-code commands + * + */ +//#define M120_M121_ENABLED //Be careful enabling and using these G-code commands. + //=========================================================================== //============================= Define Defines ============================ //=========================================================================== diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index cc2766b4..98e5102c 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -363,8 +363,8 @@ extern bool mmu_print_saved; //estimated time to end of the print extern uint8_t print_percent_done_normal; -extern uint16_t print_time_remaining_normal; extern uint8_t print_percent_done_silent; +extern uint16_t print_time_remaining_normal; extern uint16_t print_time_remaining_silent; extern uint16_t print_time_to_change_normal; extern uint16_t print_time_to_change_silent; @@ -376,7 +376,7 @@ extern uint16_t gcode_in_progress; extern LongTimer safetyTimer; -#define PRINT_PERCENT_DONE_INIT 0xff +#define PRINT_PERCENT_DONE_INIT 0xff #define PRINTER_ACTIVE (IS_SD_PRINTING || is_usb_printing || isPrintPaused || (custom_message_type == CustomMsg::TempCal) || saved_printing || (lcd_commands_type == LcdCommands::Layer1Cal) || mmu_print_saved || homing_flag || mesh_bed_leveling_flag) //! Beware - mcode_in_progress is set as soon as the command gets really processed, diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 547f4e21..68933093 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -103,10 +103,10 @@ #include "tmc2130.h" #endif //TMC2130 -#ifdef W25X20CL -#include "w25x20cl.h" -#include "optiboot_w25x20cl.h" -#endif //W25X20CL +#ifdef XFLASH +#include "xflash.h" +#include "optiboot_xflash.h" +#endif //XFLASH #ifdef BLINKM #include "BlinkM.h" @@ -219,7 +219,7 @@ unsigned int heating_status; unsigned int heating_status_counter; bool loading_flag = false; - +#define XY_NO_RESTORE_FLAG (mesh_bed_leveling_flag || homing_flag) char snmm_filaments_used = 0; @@ -305,7 +305,12 @@ bool no_response = false; uint8_t important_status; uint8_t saved_filament_type; -#define SAVED_TARGET_UNSET (X_MIN_POS-1) +// Define some coordinates outside the clamp limits (making them invalid past the parsing stage) so +// that they can be used later for various logical checks +#define X_COORD_INVALID (X_MIN_POS-1) +#define Y_COORD_INVALID (Y_MIN_POS-1) + +#define SAVED_TARGET_UNSET X_COORD_INVALID float saved_target[NUM_AXIS] = {SAVED_TARGET_UNSET, 0, 0, 0}; // save/restore printing in case that mmu was not responding @@ -313,8 +318,8 @@ bool mmu_print_saved = false; // storing estimated time to end of print counted by slicer uint8_t print_percent_done_normal = PRINT_PERCENT_DONE_INIT; -uint16_t print_time_remaining_normal = PRINT_TIME_REMAINING_INIT; //estimated remaining print time in minutes uint8_t print_percent_done_silent = PRINT_PERCENT_DONE_INIT; +uint16_t print_time_remaining_normal = PRINT_TIME_REMAINING_INIT; //estimated remaining print time in minutes uint16_t print_time_remaining_silent = PRINT_TIME_REMAINING_INIT; //estimated remaining print time in minutes uint16_t print_time_to_change_normal = PRINT_TIME_REMAINING_INIT; //estimated remaining time to next change in minutes uint16_t print_time_to_change_silent = PRINT_TIME_REMAINING_INIT; //estimated remaining time to next change in minutes @@ -375,7 +380,7 @@ boolean chdkActive = false; bool saved_printing = false; //!< Print is paused and saved in RAM static uint32_t saved_sdpos = 0; //!< SD card position, or line number in case of USB printing uint8_t saved_printing_type = PRINTING_TYPE_SD; -static float saved_pos[4] = { 0, 0, 0, 0 }; +static float saved_pos[4] = { X_COORD_INVALID, 0, 0, 0 }; static uint16_t saved_feedrate2 = 0; //!< Default feedrate (truncated from float) static int saved_feedmultiply2 = 0; static uint8_t saved_active_extruder = 0; @@ -588,19 +593,6 @@ void crashdet_restore_print_and_continue() // babystep_apply(); } - -void crashdet_stop_and_save_print2() -{ - cli(); - planner_abort_hard(); //abort printing - cmdqueue_reset(); //empty cmdqueue - card.sdprinting = false; - card.closefile(); - // Reset and re-enable the stepper timer just before the global interrupts are enabled. - st_reset_timer(); - sei(); -} - void crashdet_detected(uint8_t mask) { st_synchronize(); @@ -910,7 +902,7 @@ uint8_t check_printer_version() #if (LANG_MODE != 0) //secondary language support -#ifdef W25X20CL +#ifdef XFLASH // language update from external flash @@ -936,7 +928,7 @@ void update_sec_lang_from_external_flash() cli(); uint16_t size = header.size - state * LANGBOOT_BLOCKSIZE; if (size > LANGBOOT_BLOCKSIZE) size = LANGBOOT_BLOCKSIZE; - w25x20cl_rd_data(src_addr + state * LANGBOOT_BLOCKSIZE, (uint8_t*)LANGBOOT_RAMBUFFER, size); + xflash_rd_data(src_addr + state * LANGBOOT_BLOCKSIZE, (uint8_t*)LANGBOOT_RAMBUFFER, size); if (state == 0) { //TODO - check header integrity @@ -954,7 +946,7 @@ void update_sec_lang_from_external_flash() } -#ifdef DEBUG_W25X20CL +#ifdef DEBUG_XFLASH uint8_t lang_xflash_enum_codes(uint16_t* codes) { @@ -964,7 +956,7 @@ uint8_t lang_xflash_enum_codes(uint16_t* codes) while (1) { printf_P(_n("LANGTABLE%d:"), count); - w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); + xflash_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); if (header.magic != LANG_MAGIC) { puts_P(_n("NG!")); @@ -992,17 +984,17 @@ void list_sec_lang_from_external_flash() printf_P(_n("XFlash lang count = %hhd\n"), count); } -#endif //DEBUG_W25X20CL +#endif //DEBUG_XFLASH -#endif //W25X20CL +#endif //XFLASH #endif //(LANG_MODE != 0) -static void w25x20cl_err_msg() +static void xflash_err_msg() { lcd_clear(); - lcd_puts_P(_n("External SPI flash\nW25X20CL is not res-\nponding. Language\nswitch unavailable.")); + lcd_puts_P(_n("External SPI flash\nXFLASH is not res-\nponding. Language\nswitch unavailable.")); } // "Setup" function is called by the Arduino framework on startup. @@ -1028,23 +1020,23 @@ void setup() fdev_setup_stream(uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE); //setup uart out stream stdout = uartout; -#ifdef W25X20CL - bool w25x20cl_success = w25x20cl_init(); +#ifdef XFLASH + bool xflash_success = xflash_init(); uint8_t optiboot_status = 1; - if (w25x20cl_success) + if (xflash_success) { - optiboot_status = optiboot_w25x20cl_enter(); + optiboot_status = optiboot_xflash_enter(); #if (LANG_MODE != 0) //secondary language support update_sec_lang_from_external_flash(); #endif //(LANG_MODE != 0) } else { - w25x20cl_err_msg(); + xflash_err_msg(); } #else - const bool w25x20cl_success = true; -#endif //W25X20CL + const bool xflash_success = true; +#endif //XFLASH setup_killpin(); @@ -1091,7 +1083,7 @@ void setup() } -#ifndef W25X20CL +#ifndef XFLASH SERIAL_PROTOCOLLNPGM("start"); #else if ((optiboot_status != 0) || (selectedSerialPort != 0)) @@ -1172,7 +1164,7 @@ void setup() #undef LT_PRINT_TEST #if 0 - w25x20cl_rd_data(0x25ba, (uint8_t*)&block_buffer, 1024); + xflash_rd_data(0x25ba, (uint8_t*)&block_buffer, 1024); for (uint16_t i = 0; i < 1024; i++) { if ((i % 16) == 0) printf_P(_n("%04x:"), 0x25ba+i); @@ -1269,11 +1261,11 @@ void setup() tp_init(); // Initialize temperature loop - if (w25x20cl_success) lcd_splash(); // we need to do this again, because tp_init() kills lcd + if (xflash_success) lcd_splash(); // we need to do this again, because tp_init() kills lcd else { - w25x20cl_err_msg(); - puts_P(_n("W25X20CL not responding.")); + xflash_err_msg(); + puts_P(_n("XFLASH not responding.")); } #ifdef EXTRUDER_ALTFAN_DETECT SERIAL_ECHORPGM(_n("Extruder fan type: ")); @@ -1458,16 +1450,16 @@ void setup() #if (LANG_MODE != 0) //secondary language support -#ifdef DEBUG_W25X20CL - W25X20CL_SPI_ENTER(); +#ifdef DEBUG_XFLASH + XFLASH_SPI_ENTER(); uint8_t uid[8]; // 64bit unique id - w25x20cl_rd_uid(uid); - puts_P(_n("W25X20CL UID=")); + xflash_rd_uid(uid); + puts_P(_n("XFLASH UID=")); for (uint8_t i = 0; i < 8; i ++) printf_P(PSTR("%02hhx"), uid[i]); putchar('\n'); list_sec_lang_from_external_flash(); -#endif //DEBUG_W25X20CL +#endif //DEBUG_XFLASH // lang_reset(); if (!lang_select(eeprom_read_byte((uint8_t*)EEPROM_LANG))) @@ -2668,16 +2660,15 @@ static void gcode_G28(bool home_x_axis, long home_x_value, bool home_y_axis, lon static void gcode_G28(bool home_x_axis, long home_x_value, bool home_y_axis, long home_y_value, bool home_z_axis, long home_z_value, bool without_mbl) #endif //TMC2130 { + // Flag for the display update routine and to disable the print cancelation during homing. st_synchronize(); + homing_flag = true; #if 0 SERIAL_ECHOPGM("G28, initial "); print_world_coordinates(); SERIAL_ECHOPGM("G28, initial "); print_physical_coordinates(); #endif - // Flag for the display update routine and to disable the print cancelation during homing. - homing_flag = true; - // Which axes should be homed? bool home_x = home_x_axis; bool home_y = home_y_axis; @@ -2920,24 +2911,21 @@ static void gcode_G28(bool home_x_axis, long home_x_value, bool home_y_axis, lon #if (defined(MESH_BED_LEVELING) && !defined(MK1BP)) if (home_x_axis || home_y_axis || without_mbl || home_z_axis) - { + { if (! home_z && mbl_was_active) { // Re-enable the mesh bed leveling if only the X and Y axes were re-homed. mbl.active = true; // and re-adjust the current logical Z axis with the bed leveling offset applicable at the current XY position. current_position[Z_AXIS] -= mbl.get_z(st_get_position_mm(X_AXIS), st_get_position_mm(Y_AXIS)); } - } - else - { - st_synchronize(); - homing_flag = false; - } + } #endif if (farm_mode) { prusa_statistics(20); }; + st_synchronize(); homing_flag = false; + #if 0 SERIAL_ECHOPGM("G28, final "); print_world_coordinates(); SERIAL_ECHOPGM("G28, final "); print_physical_coordinates(); @@ -2954,6 +2942,422 @@ static void gcode_G28(bool home_x_axis, bool home_y_axis, bool home_z_axis) #endif //TMC2130 } + +// G80 - Automatic mesh bed leveling +static void gcode_G80() +{ + st_synchronize(); + if (waiting_inside_plan_buffer_line_print_aborted) + return; + + mesh_bed_leveling_flag = true; +#ifndef PINDA_THERMISTOR + static bool run = false; // thermistor-less PINDA temperature compensation is running +#endif // ndef PINDA_THERMISTOR + +#ifdef SUPPORT_VERBOSITY + int8_t verbosity_level = 0; + if (code_seen('V')) { + // Just 'V' without a number counts as V1. + char c = strchr_pointer[1]; + verbosity_level = (c == ' ' || c == '\t' || c == 0) ? 1 : code_value_short(); + } +#endif //SUPPORT_VERBOSITY + // Firstly check if we know where we are + if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])) { + // We don't know where we are! HOME! + // Push the commands to the front of the message queue in the reverse order! + // There shall be always enough space reserved for these commands. + repeatcommand_front(); // repeat G80 with all its parameters + enquecommand_front_P(G28W0); + return; + } + + uint8_t nMeasPoints = MESH_MEAS_NUM_X_POINTS; + if (code_seen('N')) { + nMeasPoints = code_value_uint8(); + if (nMeasPoints != 7) { + nMeasPoints = 3; + } + } + else { + nMeasPoints = eeprom_read_byte((uint8_t*)EEPROM_MBL_POINTS_NR); + } + + uint8_t nProbeRetry = 3; + if (code_seen('R')) { + nProbeRetry = code_value_uint8(); + if (nProbeRetry > 10) { + nProbeRetry = 10; + } + } + else { + nProbeRetry = eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR); + } + bool magnet_elimination = (eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION) > 0); + +#ifndef PINDA_THERMISTOR + if (run == false && temp_cal_active == true && calibration_status_pinda() == true && target_temperature_bed >= 50) + { + temp_compensation_start(); + run = true; + repeatcommand_front(); // repeat G80 with all its parameters + enquecommand_front_P(G28W0); + break; + } + run = false; +#endif //PINDA_THERMISTOR + // Save custom message state, set a new custom message state to display: Calibrating point 9. + CustomMsg custom_message_type_old = custom_message_type; + unsigned int custom_message_state_old = custom_message_state; + custom_message_type = CustomMsg::MeshBedLeveling; + custom_message_state = (nMeasPoints * nMeasPoints) + 10; + lcd_update(1); + + mbl.reset(); //reset mesh bed leveling + + // Reset baby stepping to zero, if the babystepping has already been loaded before. + babystep_undo(); + + // Cycle through all points and probe them + // First move up. During this first movement, the babystepping will be reverted. + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60); + // The move to the first calibration point. + current_position[X_AXIS] = BED_X0; + current_position[Y_AXIS] = BED_Y0; + +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 1) + { + bool clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); + clamped ? SERIAL_PROTOCOLPGM("First calibration point clamped.\n") : SERIAL_PROTOCOLPGM("No clamping for first calibration point.\n"); + } +#else //SUPPORT_VERBOSITY + world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); +#endif //SUPPORT_VERBOSITY + + int XY_AXIS_FEEDRATE = homing_feedrate[X_AXIS] / 20; + plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE); + // Wait until the move is finished. + st_synchronize(); + if (waiting_inside_plan_buffer_line_print_aborted) + { + custom_message_type = custom_message_type_old; + custom_message_state = custom_message_state_old; + return; + } + + uint8_t mesh_point = 0; //index number of calibration point + int Z_LIFT_FEEDRATE = homing_feedrate[Z_AXIS] / 40; + bool has_z = is_bed_z_jitter_data_valid(); //checks if we have data from Z calibration (offsets of the Z heiths of the 8 calibration points from the first point) +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 1) { + has_z ? SERIAL_PROTOCOLPGM("Z jitter data from Z cal. valid.\n") : SERIAL_PROTOCOLPGM("Z jitter data from Z cal. not valid.\n"); + } +#endif // SUPPORT_VERBOSITY + int l_feedmultiply = setup_for_endstop_move(false); //save feedrate and feedmultiply, sets feedmultiply to 100 + while (mesh_point != nMeasPoints * nMeasPoints) { + // Get coords of a measuring point. + uint8_t ix = mesh_point % nMeasPoints; // from 0 to MESH_NUM_X_POINTS - 1 + uint8_t iy = mesh_point / nMeasPoints; + /*if (!mbl_point_measurement_valid(ix, iy, nMeasPoints, true)) { + printf_P(PSTR("Skipping point [%d;%d] \n"), ix, iy); + custom_message_state--; + mesh_point++; + continue; //skip + }*/ + if (iy & 1) ix = (nMeasPoints - 1) - ix; // Zig zag + if (nMeasPoints == 7) //if we have 7x7 mesh, compare with Z-calibration for points which are in 3x3 mesh + { + has_z = ((ix % 3 == 0) && (iy % 3 == 0)) && is_bed_z_jitter_data_valid(); + } + float z0 = 0.f; + if (has_z && (mesh_point > 0)) { + uint16_t z_offset_u = 0; + if (nMeasPoints == 7) { + z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * ((ix/3) + iy - 1))); + } + else { + z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * (ix + iy * 3 - 1))); + } + z0 = mbl.z_values[0][0] + *reinterpret_cast(&z_offset_u) * 0.01; +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 1) { + printf_P(PSTR("Bed leveling, point: %d, calibration Z stored in eeprom: %d, calibration z: %f \n"), mesh_point, z_offset_u, z0); + } +#endif // SUPPORT_VERBOSITY + } + + // Move Z up to MESH_HOME_Z_SEARCH. + if((ix == 0) && (iy == 0)) current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + else current_position[Z_AXIS] += 2.f / nMeasPoints; //use relative movement from Z coordinate where PINDa triggered on previous point. This makes calibration faster. + float init_z_bckp = current_position[Z_AXIS]; + plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); + st_synchronize(); + + // Move to XY position of the sensor point. + current_position[X_AXIS] = BED_X(ix, nMeasPoints); + current_position[Y_AXIS] = BED_Y(iy, nMeasPoints); + + //printf_P(PSTR("[%f;%f]\n"), current_position[X_AXIS], current_position[Y_AXIS]); + + +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 1) { + bool clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); + SERIAL_PROTOCOL(mesh_point); + clamped ? SERIAL_PROTOCOLPGM(": xy clamped.\n") : SERIAL_PROTOCOLPGM(": no xy clamping\n"); + } +#else //SUPPORT_VERBOSITY + world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); +#endif // SUPPORT_VERBOSITY + + //printf_P(PSTR("after clamping: [%f;%f]\n"), current_position[X_AXIS], current_position[Y_AXIS]); + plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE); + st_synchronize(); + if (waiting_inside_plan_buffer_line_print_aborted) + { + custom_message_type = custom_message_type_old; + custom_message_state = custom_message_state_old; + return; + } + + // Go down until endstop is hit + const float Z_CALIBRATION_THRESHOLD = 1.f; + if (!find_bed_induction_sensor_point_z((has_z && mesh_point > 0) ? z0 - Z_CALIBRATION_THRESHOLD : -10.f, nProbeRetry)) { //if we have data from z calibration max allowed difference is 1mm for each point, if we dont have data max difference is 10mm from initial point + printf_P(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); + break; + } + if (init_z_bckp - current_position[Z_AXIS] < 0.1f) { //broken cable or initial Z coordinate too low. Go to MESH_HOME_Z_SEARCH and repeat last step (z-probe) again to distinguish between these two cases. + //printf_P(PSTR("Another attempt! Current Z position: %f\n"), current_position[Z_AXIS]); + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); + st_synchronize(); + + if (!find_bed_induction_sensor_point_z((has_z && mesh_point > 0) ? z0 - Z_CALIBRATION_THRESHOLD : -10.f, nProbeRetry)) { //if we have data from z calibration max allowed difference is 1mm for each point, if we dont have data max difference is 10mm from initial point + printf_P(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); + break; + } + if (MESH_HOME_Z_SEARCH - current_position[Z_AXIS] < 0.1f) { + puts_P(PSTR("Bed leveling failed. Sensor disconnected or cable broken.")); + break; + } + } + if (has_z && fabs(z0 - current_position[Z_AXIS]) > Z_CALIBRATION_THRESHOLD) { //if we have data from z calibration, max. allowed difference is 1mm for each point + puts_P(PSTR("Bed leveling failed. Sensor triggered too high.")); + break; + } +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 10) { + SERIAL_ECHOPGM("X: "); + MYSERIAL.print(current_position[X_AXIS], 5); + SERIAL_ECHOLNPGM(""); + SERIAL_ECHOPGM("Y: "); + MYSERIAL.print(current_position[Y_AXIS], 5); + SERIAL_PROTOCOLPGM("\n"); + } +#endif // SUPPORT_VERBOSITY + float offset_z = 0; + +#ifdef PINDA_THERMISTOR + offset_z = temp_compensation_pinda_thermistor_offset(current_temperature_pinda); +#endif //PINDA_THERMISTOR + // #ifdef SUPPORT_VERBOSITY + /* if (verbosity_level >= 1) + { + SERIAL_ECHOPGM("mesh bed leveling: "); + MYSERIAL.print(current_position[Z_AXIS], 5); + SERIAL_ECHOPGM(" offset: "); + MYSERIAL.print(offset_z, 5); + SERIAL_ECHOLNPGM(""); + }*/ + // #endif // SUPPORT_VERBOSITY + mbl.set_z(ix, iy, current_position[Z_AXIS] - offset_z); //store measured z values z_values[iy][ix] = z - offset_z; + + custom_message_state--; + mesh_point++; + lcd_update(1); + } + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 20) { + SERIAL_ECHOLNPGM("Mesh bed leveling while loop finished."); + SERIAL_ECHOLNPGM("MESH_HOME_Z_SEARCH: "); + MYSERIAL.print(current_position[Z_AXIS], 5); + } +#endif // SUPPORT_VERBOSITY + plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); + st_synchronize(); + if (mesh_point != nMeasPoints * nMeasPoints) { + Sound_MakeSound(e_SOUND_TYPE_StandardAlert); + bool bState; + do { // repeat until Z-leveling o.k. + lcd_display_message_fullscreen_P(_i("Some problem encountered, Z-leveling enforced ...")); +#ifdef TMC2130 + lcd_wait_for_click_delay(MSG_BED_LEVELING_FAILED_TIMEOUT); + calibrate_z_auto(); // Z-leveling (X-assembly stay up!!!) +#else // TMC2130 + lcd_wait_for_click_delay(0); // ~ no timeout + lcd_calibrate_z_end_stop_manual(true); // Z-leveling (X-assembly stay up!!!) +#endif // TMC2130 + // ~ Z-homing (can not be used "G28", because X & Y-homing would have been done before (Z-homing)) + bState=enable_z_endstop(false); + current_position[Z_AXIS] -= 1; + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 40); + st_synchronize(); + enable_z_endstop(true); +#ifdef TMC2130 + tmc2130_home_enter(Z_AXIS_MASK); +#endif // TMC2130 + current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; + plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 40); + st_synchronize(); +#ifdef TMC2130 + tmc2130_home_exit(); +#endif // TMC2130 + enable_z_endstop(bState); + } while (st_get_position_mm(Z_AXIS) > MESH_HOME_Z_SEARCH); // i.e. Z-leveling not o.k. + // plan_set_z_position(MESH_HOME_Z_SEARCH); // is not necessary ('do-while' loop always ends at the expected Z-position) + + custom_message_type = custom_message_type_old; + custom_message_state = custom_message_state_old; + lcd_update_enable(true); // display / status-line recovery + gcode_G28(true, true, true); // X & Y & Z-homing (must be after individual Z-homing (problem with spool-holder)!) + repeatcommand_front(); // re-run (i.e. of "G80") + return; + } + clean_up_after_endstop_move(l_feedmultiply); + // SERIAL_ECHOLNPGM("clean up finished "); + +#ifndef PINDA_THERMISTOR + if(temp_cal_active == true && calibration_status_pinda() == true) temp_compensation_apply(); //apply PINDA temperature compensation +#endif + babystep_apply(); // Apply Z height correction aka baby stepping before mesh bed leveing gets activated. + // SERIAL_ECHOLNPGM("babystep applied"); + bool eeprom_bed_correction_valid = eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1; +#ifdef SUPPORT_VERBOSITY + if (verbosity_level >= 1) { + eeprom_bed_correction_valid ? SERIAL_PROTOCOLPGM("Bed correction data valid\n") : SERIAL_PROTOCOLPGM("Bed correction data not valid\n"); + } +#endif // SUPPORT_VERBOSITY + + for (uint8_t i = 0; i < 4; ++i) { + unsigned char codes[4] = { 'L', 'R', 'F', 'B' }; + long correction = 0; + if (code_seen(codes[i])) + correction = code_value_long(); + else if (eeprom_bed_correction_valid) { + unsigned char *addr = (i < 2) ? + ((i == 0) ? (unsigned char*)EEPROM_BED_CORRECTION_LEFT : (unsigned char*)EEPROM_BED_CORRECTION_RIGHT) : + ((i == 2) ? (unsigned char*)EEPROM_BED_CORRECTION_FRONT : (unsigned char*)EEPROM_BED_CORRECTION_REAR); + correction = eeprom_read_int8(addr); + } + if (correction == 0) + continue; + + if (labs(correction) > BED_ADJUSTMENT_UM_MAX) { + SERIAL_ERROR_START; + SERIAL_ECHOPGM("Excessive bed leveling correction: "); + SERIAL_ECHO(correction); + SERIAL_ECHOLNPGM(" microns"); + } + else { + float offset = float(correction) * 0.001f; + switch (i) { + case 0: + for (uint8_t row = 0; row < nMeasPoints; ++row) { + for (uint8_t col = 0; col < nMeasPoints - 1; ++col) { + mbl.z_values[row][col] += offset * (nMeasPoints - 1 - col) / (nMeasPoints - 1); + } + } + break; + case 1: + for (uint8_t row = 0; row < nMeasPoints; ++row) { + for (uint8_t col = 1; col < nMeasPoints; ++col) { + mbl.z_values[row][col] += offset * col / (nMeasPoints - 1); + } + } + break; + case 2: + for (uint8_t col = 0; col < nMeasPoints; ++col) { + for (uint8_t row = 0; row < nMeasPoints; ++row) { + mbl.z_values[row][col] += offset * (nMeasPoints - 1 - row) / (nMeasPoints - 1); + } + } + break; + case 3: + for (uint8_t col = 0; col < nMeasPoints; ++col) { + for (uint8_t row = 1; row < nMeasPoints; ++row) { + mbl.z_values[row][col] += offset * row / (nMeasPoints - 1); + } + } + break; + } + } + } + // SERIAL_ECHOLNPGM("Bed leveling correction finished"); + if (nMeasPoints == 3) { + mbl.upsample_3x3(); //interpolation from 3x3 to 7x7 points using largrangian polynomials while using the same array z_values[iy][ix] for storing (just coppying measured data to new destination and interpolating between them) + } + /* + SERIAL_PROTOCOLPGM("Num X,Y: "); + SERIAL_PROTOCOL(MESH_NUM_X_POINTS); + SERIAL_PROTOCOLPGM(","); + SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); + SERIAL_PROTOCOLPGM("\nZ search height: "); + SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); + SERIAL_PROTOCOLLNPGM("\nMeasured points:"); + for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { + for (int x = 0; x < MESH_NUM_X_POINTS; x++) { + SERIAL_PROTOCOLPGM(" "); + SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); + } + SERIAL_PROTOCOLPGM("\n"); + } + */ + if (nMeasPoints == 7 && magnet_elimination) { + mbl_interpolation(nMeasPoints); + } + /* + SERIAL_PROTOCOLPGM("Num X,Y: "); + SERIAL_PROTOCOL(MESH_NUM_X_POINTS); + SERIAL_PROTOCOLPGM(","); + SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); + SERIAL_PROTOCOLPGM("\nZ search height: "); + SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); + SERIAL_PROTOCOLLNPGM("\nMeasured points:"); + for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { + for (int x = 0; x < MESH_NUM_X_POINTS; x++) { + SERIAL_PROTOCOLPGM(" "); + SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); + } + SERIAL_PROTOCOLPGM("\n"); + } + */ + // SERIAL_ECHOLNPGM("Upsample finished"); + mbl.active = 1; //activate mesh bed leveling + // SERIAL_ECHOLNPGM("Mesh bed leveling activated"); + go_home_with_z_lift(); + // SERIAL_ECHOLNPGM("Go home finished"); + //unretract (after PINDA preheat retraction) + if ((degHotend(active_extruder) > EXTRUDE_MINTEMP) && eeprom_read_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE) && calibration_status_pinda() && (target_temperature_bed >= 50)) { + current_position[E_AXIS] += default_retraction; + plan_buffer_line_curposXYZE(400); + } + KEEPALIVE_STATE(NOT_BUSY); + // Restore custom message state + lcd_setstatuspgm(_T(WELCOME_MSG)); + custom_message_type = custom_message_type_old; + custom_message_state = custom_message_state_old; + mesh_bed_run_from_menu = false; + lcd_update(2); + + st_synchronize(); + mesh_bed_leveling_flag = false; +} + + void adjust_bed_reset() { eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID, 1); @@ -4013,10 +4417,10 @@ void process_commands() } else if (code_seen_P(PSTR("RESET"))) { // PRUSA RESET #ifdef WATCHDOG -#if defined(W25X20CL) && defined(BOOTAPP) +#if defined(XFLASH) && defined(BOOTAPP) boot_app_magic = BOOT_APP_MAGIC; boot_app_flags = BOOT_APP_FLG_RUN; -#endif //defined(W25X20CL) && defined(BOOTAPP) +#endif //defined(XFLASH) && defined(BOOTAPP) softReset(); #elif defined(BOOTAPP) //this is a safety precaution. This is because the new bootloader turns off the heaters, but the old one doesn't. The watchdog should be used most of the time. asm volatile("jmp 0x3E000"); @@ -4530,9 +4934,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) gcode_G28(home_x, home_x_value, home_y, home_y_value, home_z, home_z_value, without_mbl); #endif //TMC2130 if ((home_x || home_y || without_mbl || home_z) == false) { - // Push the commands to the front of the message queue in the reverse order! - // There shall be always enough space reserved for these commands. - goto case_G80; + gcode_G80(); } break; } @@ -4745,8 +5147,9 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) */ case 30: { - homing_flag = true; st_synchronize(); + homing_flag = true; + // TODO: make sure the bed_level_rotation_matrix is identity or the planner will get set incorectly int l_feedmultiply = setup_for_endstop_move(); @@ -4849,7 +5252,9 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) } } + st_synchronize(); homing_flag = true; // keep homing on to avoid babystepping while the LCD is enabled + lcd_update_enable(true); KEEPALIVE_STATE(NOT_BUSY); //no need to print busy messages as we print current temperatures periodicaly SERIAL_ECHOLNPGM("PINDA probe calibration start"); @@ -5084,404 +5489,11 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) * v Y-axis */ - case 80: - + case 80: { #ifdef MK1BP break; #endif //MK1BP - case_G80: - { - mesh_bed_leveling_flag = true; -#ifndef PINDA_THERMISTOR - static bool run = false; // thermistor-less PINDA temperature compensation is running -#endif // ndef PINDA_THERMISTOR - -#ifdef SUPPORT_VERBOSITY - int8_t verbosity_level = 0; - if (code_seen('V')) { - // Just 'V' without a number counts as V1. - char c = strchr_pointer[1]; - verbosity_level = (c == ' ' || c == '\t' || c == 0) ? 1 : code_value_short(); - } -#endif //SUPPORT_VERBOSITY - // Firstly check if we know where we are - if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])) { - // We don't know where we are! HOME! - // Push the commands to the front of the message queue in the reverse order! - // There shall be always enough space reserved for these commands. - repeatcommand_front(); // repeat G80 with all its parameters - enquecommand_front_P(G28W0); - break; - } - - uint8_t nMeasPoints = MESH_MEAS_NUM_X_POINTS; - if (code_seen('N')) { - nMeasPoints = code_value_uint8(); - if (nMeasPoints != 7) { - nMeasPoints = 3; - } - } - else { - nMeasPoints = eeprom_read_byte((uint8_t*)EEPROM_MBL_POINTS_NR); - } - - uint8_t nProbeRetry = 3; - if (code_seen('R')) { - nProbeRetry = code_value_uint8(); - if (nProbeRetry > 10) { - nProbeRetry = 10; - } - } - else { - nProbeRetry = eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR); - } - bool magnet_elimination = (eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION) > 0); - -#ifndef PINDA_THERMISTOR - if (run == false && temp_cal_active == true && calibration_status_pinda() == true && target_temperature_bed >= 50) - { - temp_compensation_start(); - run = true; - repeatcommand_front(); // repeat G80 with all its parameters - enquecommand_front_P(G28W0); - break; - } - run = false; -#endif //PINDA_THERMISTOR - // Save custom message state, set a new custom message state to display: Calibrating point 9. - CustomMsg custom_message_type_old = custom_message_type; - unsigned int custom_message_state_old = custom_message_state; - custom_message_type = CustomMsg::MeshBedLeveling; - custom_message_state = (nMeasPoints * nMeasPoints) + 10; - lcd_update(1); - - mbl.reset(); //reset mesh bed leveling - - // Reset baby stepping to zero, if the babystepping has already been loaded before. - babystep_undo(); - - // Cycle through all points and probe them - // First move up. During this first movement, the babystepping will be reverted. - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60); - // The move to the first calibration point. - current_position[X_AXIS] = BED_X0; - current_position[Y_AXIS] = BED_Y0; - - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) - { - bool clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - clamped ? SERIAL_PROTOCOLPGM("First calibration point clamped.\n") : SERIAL_PROTOCOLPGM("No clamping for first calibration point.\n"); - } - #else //SUPPORT_VERBOSITY - world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - #endif //SUPPORT_VERBOSITY - - plan_buffer_line_curposXYZE(homing_feedrate[X_AXIS] / 30); - // Wait until the move is finished. - st_synchronize(); - - uint8_t mesh_point = 0; //index number of calibration point - - int XY_AXIS_FEEDRATE = homing_feedrate[X_AXIS] / 20; - int Z_LIFT_FEEDRATE = homing_feedrate[Z_AXIS] / 40; - bool has_z = is_bed_z_jitter_data_valid(); //checks if we have data from Z calibration (offsets of the Z heiths of the 8 calibration points from the first point) - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - has_z ? SERIAL_PROTOCOLPGM("Z jitter data from Z cal. valid.\n") : SERIAL_PROTOCOLPGM("Z jitter data from Z cal. not valid.\n"); - } - #endif // SUPPORT_VERBOSITY - int l_feedmultiply = setup_for_endstop_move(false); //save feedrate and feedmultiply, sets feedmultiply to 100 - while (mesh_point != nMeasPoints * nMeasPoints) { - // Get coords of a measuring point. - uint8_t ix = mesh_point % nMeasPoints; // from 0 to MESH_NUM_X_POINTS - 1 - uint8_t iy = mesh_point / nMeasPoints; - /*if (!mbl_point_measurement_valid(ix, iy, nMeasPoints, true)) { - printf_P(PSTR("Skipping point [%d;%d] \n"), ix, iy); - custom_message_state--; - mesh_point++; - continue; //skip - }*/ - if (iy & 1) ix = (nMeasPoints - 1) - ix; // Zig zag - if (nMeasPoints == 7) //if we have 7x7 mesh, compare with Z-calibration for points which are in 3x3 mesh - { - has_z = ((ix % 3 == 0) && (iy % 3 == 0)) && is_bed_z_jitter_data_valid(); - } - float z0 = 0.f; - if (has_z && (mesh_point > 0)) { - uint16_t z_offset_u = 0; - if (nMeasPoints == 7) { - z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * ((ix/3) + iy - 1))); - } - else { - z_offset_u = eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + 2 * (ix + iy * 3 - 1))); - } - z0 = mbl.z_values[0][0] + *reinterpret_cast(&z_offset_u) * 0.01; - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - printf_P(PSTR("Bed leveling, point: %d, calibration Z stored in eeprom: %d, calibration z: %f \n"), mesh_point, z_offset_u, z0); - } - #endif // SUPPORT_VERBOSITY - } - - // Move Z up to MESH_HOME_Z_SEARCH. - if((ix == 0) && (iy == 0)) current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - else current_position[Z_AXIS] += 2.f / nMeasPoints; //use relative movement from Z coordinate where PINDa triggered on previous point. This makes calibration faster. - float init_z_bckp = current_position[Z_AXIS]; - plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); - st_synchronize(); - - // Move to XY position of the sensor point. - current_position[X_AXIS] = BED_X(ix, nMeasPoints); - current_position[Y_AXIS] = BED_Y(iy, nMeasPoints); - - //printf_P(PSTR("[%f;%f]\n"), current_position[X_AXIS], current_position[Y_AXIS]); - - - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - bool clamped = world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - SERIAL_PROTOCOL(mesh_point); - clamped ? SERIAL_PROTOCOLPGM(": xy clamped.\n") : SERIAL_PROTOCOLPGM(": no xy clamping\n"); - } - #else //SUPPORT_VERBOSITY - world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]); - #endif // SUPPORT_VERBOSITY - - //printf_P(PSTR("after clamping: [%f;%f]\n"), current_position[X_AXIS], current_position[Y_AXIS]); - plan_buffer_line_curposXYZE(XY_AXIS_FEEDRATE); - st_synchronize(); - - // Go down until endstop is hit - const float Z_CALIBRATION_THRESHOLD = 1.f; - if (!find_bed_induction_sensor_point_z((has_z && mesh_point > 0) ? z0 - Z_CALIBRATION_THRESHOLD : -10.f, nProbeRetry)) { //if we have data from z calibration max allowed difference is 1mm for each point, if we dont have data max difference is 10mm from initial point - printf_P(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); - break; - } - if (init_z_bckp - current_position[Z_AXIS] < 0.1f) { //broken cable or initial Z coordinate too low. Go to MESH_HOME_Z_SEARCH and repeat last step (z-probe) again to distinguish between these two cases. - //printf_P(PSTR("Another attempt! Current Z position: %f\n"), current_position[Z_AXIS]); - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); - st_synchronize(); - - if (!find_bed_induction_sensor_point_z((has_z && mesh_point > 0) ? z0 - Z_CALIBRATION_THRESHOLD : -10.f, nProbeRetry)) { //if we have data from z calibration max allowed difference is 1mm for each point, if we dont have data max difference is 10mm from initial point - printf_P(_T(MSG_BED_LEVELING_FAILED_POINT_LOW)); - break; - } - if (MESH_HOME_Z_SEARCH - current_position[Z_AXIS] < 0.1f) { - puts_P(PSTR("Bed leveling failed. Sensor disconnected or cable broken.")); - break; - } - } - if (has_z && fabs(z0 - current_position[Z_AXIS]) > Z_CALIBRATION_THRESHOLD) { //if we have data from z calibration, max. allowed difference is 1mm for each point - puts_P(PSTR("Bed leveling failed. Sensor triggered too high.")); - break; - } - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 10) { - SERIAL_ECHOPGM("X: "); - MYSERIAL.print(current_position[X_AXIS], 5); - SERIAL_ECHOLNPGM(""); - SERIAL_ECHOPGM("Y: "); - MYSERIAL.print(current_position[Y_AXIS], 5); - SERIAL_PROTOCOLPGM("\n"); - } - #endif // SUPPORT_VERBOSITY - float offset_z = 0; - -#ifdef PINDA_THERMISTOR - offset_z = temp_compensation_pinda_thermistor_offset(current_temperature_pinda); -#endif //PINDA_THERMISTOR -// #ifdef SUPPORT_VERBOSITY -/* if (verbosity_level >= 1) - { - SERIAL_ECHOPGM("mesh bed leveling: "); - MYSERIAL.print(current_position[Z_AXIS], 5); - SERIAL_ECHOPGM(" offset: "); - MYSERIAL.print(offset_z, 5); - SERIAL_ECHOLNPGM(""); - }*/ -// #endif // SUPPORT_VERBOSITY - mbl.set_z(ix, iy, current_position[Z_AXIS] - offset_z); //store measured z values z_values[iy][ix] = z - offset_z; - - custom_message_state--; - mesh_point++; - lcd_update(1); - } - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 20) { - SERIAL_ECHOLNPGM("Mesh bed leveling while loop finished."); - SERIAL_ECHOLNPGM("MESH_HOME_Z_SEARCH: "); - MYSERIAL.print(current_position[Z_AXIS], 5); - } - #endif // SUPPORT_VERBOSITY - plan_buffer_line_curposXYZE(Z_LIFT_FEEDRATE); - st_synchronize(); - if (mesh_point != nMeasPoints * nMeasPoints) { - Sound_MakeSound(e_SOUND_TYPE_StandardAlert); - bool bState; - do { // repeat until Z-leveling o.k. - lcd_display_message_fullscreen_P(_i("Some problem encountered, Z-leveling enforced ...")); -#ifdef TMC2130 - lcd_wait_for_click_delay(MSG_BED_LEVELING_FAILED_TIMEOUT); - calibrate_z_auto(); // Z-leveling (X-assembly stay up!!!) -#else // TMC2130 - lcd_wait_for_click_delay(0); // ~ no timeout - lcd_calibrate_z_end_stop_manual(true); // Z-leveling (X-assembly stay up!!!) -#endif // TMC2130 - // ~ Z-homing (can not be used "G28", because X & Y-homing would have been done before (Z-homing)) - bState=enable_z_endstop(false); - current_position[Z_AXIS] -= 1; - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 40); - st_synchronize(); - enable_z_endstop(true); -#ifdef TMC2130 - tmc2130_home_enter(Z_AXIS_MASK); -#endif // TMC2130 - current_position[Z_AXIS] = MESH_HOME_Z_SEARCH; - plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 40); - st_synchronize(); -#ifdef TMC2130 - tmc2130_home_exit(); -#endif // TMC2130 - enable_z_endstop(bState); - } while (st_get_position_mm(Z_AXIS) > MESH_HOME_Z_SEARCH); // i.e. Z-leveling not o.k. -// plan_set_z_position(MESH_HOME_Z_SEARCH); // is not necessary ('do-while' loop always ends at the expected Z-position) - custom_message_type=CustomMsg::Status; // display / status-line recovery - lcd_update_enable(true); // display / status-line recovery - gcode_G28(true, true, true); // X & Y & Z-homing (must be after individual Z-homing (problem with spool-holder)!) - repeatcommand_front(); // re-run (i.e. of "G80") - break; - } - clean_up_after_endstop_move(l_feedmultiply); -// SERIAL_ECHOLNPGM("clean up finished "); - -#ifndef PINDA_THERMISTOR - if(temp_cal_active == true && calibration_status_pinda() == true) temp_compensation_apply(); //apply PINDA temperature compensation -#endif - babystep_apply(); // Apply Z height correction aka baby stepping before mesh bed leveing gets activated. -// SERIAL_ECHOLNPGM("babystep applied"); - bool eeprom_bed_correction_valid = eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1; - #ifdef SUPPORT_VERBOSITY - if (verbosity_level >= 1) { - eeprom_bed_correction_valid ? SERIAL_PROTOCOLPGM("Bed correction data valid\n") : SERIAL_PROTOCOLPGM("Bed correction data not valid\n"); - } - #endif // SUPPORT_VERBOSITY - - for (uint8_t i = 0; i < 4; ++i) { - unsigned char codes[4] = { 'L', 'R', 'F', 'B' }; - long correction = 0; - if (code_seen(codes[i])) - correction = code_value_long(); - else if (eeprom_bed_correction_valid) { - unsigned char *addr = (i < 2) ? - ((i == 0) ? (unsigned char*)EEPROM_BED_CORRECTION_LEFT : (unsigned char*)EEPROM_BED_CORRECTION_RIGHT) : - ((i == 2) ? (unsigned char*)EEPROM_BED_CORRECTION_FRONT : (unsigned char*)EEPROM_BED_CORRECTION_REAR); - correction = eeprom_read_int8(addr); - } - if (correction == 0) - continue; - - if (labs(correction) > BED_ADJUSTMENT_UM_MAX) { - SERIAL_ERROR_START; - SERIAL_ECHOPGM("Excessive bed leveling correction: "); - SERIAL_ECHO(correction); - SERIAL_ECHOLNPGM(" microns"); - } - else { - float offset = float(correction) * 0.001f; - switch (i) { - case 0: - for (uint8_t row = 0; row < nMeasPoints; ++row) { - for (uint8_t col = 0; col < nMeasPoints - 1; ++col) { - mbl.z_values[row][col] += offset * (nMeasPoints - 1 - col) / (nMeasPoints - 1); - } - } - break; - case 1: - for (uint8_t row = 0; row < nMeasPoints; ++row) { - for (uint8_t col = 1; col < nMeasPoints; ++col) { - mbl.z_values[row][col] += offset * col / (nMeasPoints - 1); - } - } - break; - case 2: - for (uint8_t col = 0; col < nMeasPoints; ++col) { - for (uint8_t row = 0; row < nMeasPoints; ++row) { - mbl.z_values[row][col] += offset * (nMeasPoints - 1 - row) / (nMeasPoints - 1); - } - } - break; - case 3: - for (uint8_t col = 0; col < nMeasPoints; ++col) { - for (uint8_t row = 1; row < nMeasPoints; ++row) { - mbl.z_values[row][col] += offset * row / (nMeasPoints - 1); - } - } - break; - } - } - } -// SERIAL_ECHOLNPGM("Bed leveling correction finished"); - if (nMeasPoints == 3) { - mbl.upsample_3x3(); //interpolation from 3x3 to 7x7 points using largrangian polynomials while using the same array z_values[iy][ix] for storing (just coppying measured data to new destination and interpolating between them) - } -/* - SERIAL_PROTOCOLPGM("Num X,Y: "); - SERIAL_PROTOCOL(MESH_NUM_X_POINTS); - SERIAL_PROTOCOLPGM(","); - SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); - SERIAL_PROTOCOLPGM("\nZ search height: "); - SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); - SERIAL_PROTOCOLLNPGM("\nMeasured points:"); - for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { - for (int x = 0; x < MESH_NUM_X_POINTS; x++) { - SERIAL_PROTOCOLPGM(" "); - SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); - } - SERIAL_PROTOCOLPGM("\n"); - } -*/ - if (nMeasPoints == 7 && magnet_elimination) { - mbl_interpolation(nMeasPoints); - } -/* - SERIAL_PROTOCOLPGM("Num X,Y: "); - SERIAL_PROTOCOL(MESH_NUM_X_POINTS); - SERIAL_PROTOCOLPGM(","); - SERIAL_PROTOCOL(MESH_NUM_Y_POINTS); - SERIAL_PROTOCOLPGM("\nZ search height: "); - SERIAL_PROTOCOL(MESH_HOME_Z_SEARCH); - SERIAL_PROTOCOLLNPGM("\nMeasured points:"); - for (int y = MESH_NUM_Y_POINTS-1; y >= 0; y--) { - for (int x = 0; x < MESH_NUM_X_POINTS; x++) { - SERIAL_PROTOCOLPGM(" "); - SERIAL_PROTOCOL_F(mbl.z_values[y][x], 5); - } - SERIAL_PROTOCOLPGM("\n"); - } -*/ -// SERIAL_ECHOLNPGM("Upsample finished"); - mbl.active = 1; //activate mesh bed leveling -// SERIAL_ECHOLNPGM("Mesh bed leveling activated"); - go_home_with_z_lift(); -// SERIAL_ECHOLNPGM("Go home finished"); - //unretract (after PINDA preheat retraction) - if ((degHotend(active_extruder) > EXTRUDE_MINTEMP) && eeprom_read_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE) && calibration_status_pinda() && (target_temperature_bed >= 50)) { - current_position[E_AXIS] += default_retraction; - plan_buffer_line_curposXYZE(400); - } - KEEPALIVE_STATE(NOT_BUSY); - // Restore custom message state - lcd_setstatuspgm(_T(WELCOME_MSG)); - custom_message_type = custom_message_type_old; - custom_message_state = custom_message_state_old; - mesh_bed_leveling_flag = false; - mesh_bed_run_from_menu = false; - lcd_update(2); - + gcode_G80(); } break; @@ -6389,14 +6401,19 @@ Sigma_Exit: if(code_seen('R')) print_time_remaining_normal = code_value(); if(code_seen('Q')) print_percent_done_silent = code_value(); if(code_seen('S')) print_time_remaining_silent = code_value(); - if(code_seen('C')) print_time_to_change_normal = code_value(); - if(code_seen('D')) print_time_to_change_silent = code_value(); - - { - const char* _msg_mode_done_remain = _N("%S MODE: Percent done: %d; print time remaining in mins: %d; Change in mins: %d\n"); - printf_P(_msg_mode_done_remain, _N("NORMAL"), int(print_percent_done_normal), print_time_remaining_normal, print_time_to_change_normal); - printf_P(_msg_mode_done_remain, _N("SILENT"), int(print_percent_done_silent), print_time_remaining_silent, print_time_to_change_silent); - } + if(code_seen('C')){ + float print_time_to_change_normal_f = code_value_float(); + print_time_to_change_normal = ( print_time_to_change_normal_f <= 0 ) ? PRINT_TIME_REMAINING_INIT : print_time_to_change_normal_f; + } + if(code_seen('D')){ + float print_time_to_change_silent_f = code_value_float(); + print_time_to_change_silent = ( print_time_to_change_silent_f <= 0 ) ? PRINT_TIME_REMAINING_INIT : print_time_to_change_silent_f; + } + { + const char* _msg_mode_done_remain = _N("%S MODE: Percent done: %hhd; print time remaining in mins: %d; Change in mins: %d\n"); + printf_P(_msg_mode_done_remain, _N("NORMAL"), int8_t(print_percent_done_normal), print_time_remaining_normal, print_time_to_change_normal); + printf_P(_msg_mode_done_remain, _N("SILENT"), int8_t(print_percent_done_silent), print_time_remaining_silent, print_time_to_change_silent); + } break; } /*! @@ -6967,19 +6984,21 @@ Sigma_Exit: lcd_setstatus(strchr_pointer + 5); break;*/ +#ifdef M120_M121_ENABLED /*! - ### M120 - Enable endstops M120: Enable endstop detection + ### M120 - Enable endstops M120: Enable endstop detection */ case 120: enable_endstops(true) ; break; /*! - ### M121 - Disable endstops M121: Disable endstop detection + ### M121 - Disable endstops M121: Disable endstop detection */ case 121: enable_endstops(false) ; break; +#endif //M120_M121_ENABLED /*! ### M119 - Get endstop states M119: Get Endstop Status @@ -10844,8 +10863,9 @@ void uvlo_() } // save the global state at planning time + bool pos_invalid = XY_NO_RESTORE_FLAG; uint16_t feedrate_bckp; - if (current_block) + if (current_block && !pos_invalid) { memcpy(saved_target, current_block->gcode_target, sizeof(saved_target)); feedrate_bckp = current_block->gcode_feedrate; @@ -10923,8 +10943,13 @@ void uvlo_() eeprom_update_word((uint16_t*)(EEPROM_UVLO_Z_MICROSTEPS), z_microsteps); // Store the current position. - eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0), current_position[X_AXIS]); - eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 4), current_position[Y_AXIS]); + if (pos_invalid) + eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0), X_COORD_INVALID); + else + { + eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0), current_position[X_AXIS]); + eeprom_update_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 4), current_position[Y_AXIS]); + } // Store the current feed rate, temperatures, fan speed and extruder multipliers (flow rates) eeprom_update_word((uint16_t*)EEPROM_UVLO_FEEDRATE, feedrate_bckp); @@ -11182,11 +11207,6 @@ bool recover_machine_state_after_power_panic() // Recover last E axis position current_position[E_AXIS] = eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION_E)); - memcpy(destination, current_position, sizeof(destination)); - - SERIAL_ECHOPGM("recover_machine_state_after_power_panic, initial "); - print_world_coordinates(); - // 3) Initialize the logical to physical coordinate system transformation. world2machine_initialize(); // SERIAL_ECHOPGM("recover_machine_state_after_power_panic, initial "); @@ -11198,7 +11218,11 @@ bool recover_machine_state_after_power_panic() // 5) Set the physical positions from the logical positions using the world2machine transformation // This is only done to inizialize Z/E axes with physical locations, since X/Y are unknown. + clamp_to_software_endstops(current_position); + memcpy(destination, current_position, sizeof(destination)); plan_set_position_curposXYZE(); + SERIAL_ECHOPGM("recover_machine_state_after_power_panic, initial "); + print_world_coordinates(); // 6) Power up the Z motors, mark their positions as known. axis_known_position[Z_AXIS] = true; @@ -11235,7 +11259,7 @@ void restore_print_from_eeprom(bool mbl_was_active) { int feedrate_rec; int feedmultiply_rec; uint8_t fan_speed_rec; - char cmd[30]; + char cmd[48]; char filename[13]; uint8_t depth = 0; char dir_name[9]; @@ -11276,10 +11300,13 @@ void restore_print_from_eeprom(bool mbl_was_active) { // Move to the XY print position in logical coordinates, where the print has been killed, but // without shifting Z along the way. This requires performing the move without mbl. - sprintf_P(cmd, PSTR("G1 X%f Y%f F3000"), - eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0)), - eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 4))); - enquecommand(cmd); + float pos_x = eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 0)); + float pos_y = eeprom_read_float((float*)(EEPROM_UVLO_CURRENT_POSITION + 4)); + if (pos_x != X_COORD_INVALID) + { + sprintf_P(cmd, PSTR("G1 X%f Y%f F3000"), pos_x, pos_y); + enquecommand(cmd); + } // Enable MBL and switch to logical positioning if (mbl_was_active) @@ -11459,7 +11486,8 @@ void stop_and_save_print_to_ram(float z_move, float e_move) #endif // save the global state at planning time - if (current_block) + bool pos_invalid = XY_NO_RESTORE_FLAG; + if (current_block && !pos_invalid) { memcpy(saved_target, current_block->gcode_target, sizeof(saved_target)); saved_feedrate2 = current_block->gcode_feedrate; @@ -11471,7 +11499,10 @@ void stop_and_save_print_to_ram(float z_move, float e_move) } planner_abort_hard(); //abort printing + memcpy(saved_pos, current_position, sizeof(saved_pos)); + if (pos_invalid) saved_pos[X_AXIS] = X_COORD_INVALID; + saved_feedmultiply2 = feedmultiply; //save feedmultiply saved_active_extruder = active_extruder; //save active_extruder saved_extruder_temperature = degTargetHotend(active_extruder); @@ -11565,6 +11596,13 @@ void restore_print_from_ram_and_continue(float e_move) fans_check_enabled = false; #endif + // do not restore XY for commands that do not require that + if (saved_pos[X_AXIS] == X_COORD_INVALID) + { + saved_pos[X_AXIS] = current_position[X_AXIS]; + saved_pos[Y_AXIS] = current_position[Y_AXIS]; + } + //first move print head in XY to the saved position: plan_buffer_line(saved_pos[X_AXIS], saved_pos[Y_AXIS], current_position[Z_AXIS], saved_pos[E_AXIS] - e_move, homing_feedrate[Z_AXIS]/13, active_extruder); //then move Z diff --git a/Firmware/SdFile.cpp b/Firmware/SdFile.cpp index 1bad4319..e21144ee 100644 --- a/Firmware/SdFile.cpp +++ b/Firmware/SdFile.cpp @@ -178,14 +178,17 @@ eof_or_fail: } bool SdFile::gfEnsureBlock(){ - if ( vol_->cacheRawBlock(gfBlock, SdVolume::CACHE_FOR_READ)){ + // this comparison is heavy-weight, especially when there is another one inside cacheRawBlock + // but it is necessary to avoid computing of terminateOfs if not needed + if( gfBlock != vol_->cacheBlockNumber_ ){ + if ( ! vol_->cacheRawBlock(gfBlock, SdVolume::CACHE_FOR_READ)){ + return false; + } // terminate with a '\n' - const uint16_t terminateOfs = fileSize_ - gfOffset; + const uint32_t terminateOfs = fileSize_ - gfOffset; vol_->cache()->data[ terminateOfs < 512 ? terminateOfs : 512 ] = '\n'; - return true; - } else { - return false; } + return true; } bool SdFile::gfComputeNextFileBlock() { diff --git a/Firmware/cardreader.h b/Firmware/cardreader.h index 715d82fa..47343e23 100644 --- a/Firmware/cardreader.h +++ b/Firmware/cardreader.h @@ -59,9 +59,12 @@ public: FORCE_INLINE bool isFileOpen() { return file.isOpen(); } bool eof() { return sdpos>=filesize; } - // There may be a potential performance problem - when the comment reading fails, sdpos points to the last correctly read character. - // However, repeated reading (e.g. after power panic) the comment will be read again - it should survive correctly, it will just take a few moments to skip - FORCE_INLINE int16_t getFilteredGcodeChar() { sdpos = file.curPosition();return (int16_t)file.readFilteredGcode();}; + FORCE_INLINE int16_t getFilteredGcodeChar() + { + int16_t c = (int16_t)file.readFilteredGcode(); + sdpos = file.curPosition(); + return c; + }; void setIndex(long index) {sdpos = index;file.seekSetFilteredGcode(index);}; FORCE_INLINE uint8_t percentDone(){if(!isFileOpen()) return 0; if(filesize) return sdpos/((filesize+99)/100); else return 0;}; FORCE_INLINE char* getWorkDirName(){workDir.getFilename(filename);return filename;}; diff --git a/Firmware/cmdqueue.cpp b/Firmware/cmdqueue.cpp index a400a4e1..3bde3336 100755 --- a/Firmware/cmdqueue.cpp +++ b/Firmware/cmdqueue.cpp @@ -600,7 +600,7 @@ void get_command() } // The new command buffer could be updated non-atomically, because it is not yet considered // to be inside the active queue. - sd_count.value = (card.get_sdpos()+1) - sdpos_atomic; + sd_count.value = card.get_sdpos() - sdpos_atomic; cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_SDCARD; cmdbuffer[bufindw+1] = sd_count.lohi.lo; cmdbuffer[bufindw+2] = sd_count.lohi.hi; @@ -625,7 +625,7 @@ void get_command() // or a 115200 Bd serial line receive interrupt, which will not trigger faster than 12kHz. ++ buflen; bufindw += len; - sdpos_atomic = card.get_sdpos()+1; + sdpos_atomic = card.get_sdpos(); if (bufindw == sizeof(cmdbuffer)) bufindw = 0; sei(); diff --git a/Firmware/config.h b/Firmware/config.h index 87599b64..2ec2077e 100644 --- a/Firmware/config.h +++ b/Firmware/config.h @@ -54,14 +54,6 @@ #define TMC2130_SPCR SPI_SPCR(TMC2130_SPI_RATE, 1, 1, 1, 0) #define TMC2130_SPSR SPI_SPSR(TMC2130_SPI_RATE) -//W25X20CL configuration -//pinout: -#define W25X20CL_PIN_CS 32 -//spi: -#define W25X20CL_SPI_RATE 0 // fosc/4 = 4MHz -#define W25X20CL_SPCR SPI_SPCR(W25X20CL_SPI_RATE, 1, 1, 1, 0) -#define W25X20CL_SPSR SPI_SPSR(W25X20CL_SPI_RATE) - //LANG - Multi-language support //#define LANG_MODE 0 // primary language only #define LANG_MODE 1 // sec. language support diff --git a/Firmware/eeprom.cpp b/Firmware/eeprom.cpp index 4f519cae..d24e11b7 100644 --- a/Firmware/eeprom.cpp +++ b/Firmware/eeprom.cpp @@ -97,6 +97,9 @@ void eeprom_init() #ifdef PINDA_TEMP_COMP if (eeprom_read_byte((uint8_t*)EEPROM_PINDA_TEMP_COMPENSATION) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_PINDA_TEMP_COMPENSATION, 0); #endif //PINDA_TEMP_COMP + + if (eeprom_read_dword((uint32_t*)EEPROM_JOB_ID) == EEPROM_EMPTY_VALUE32) + eeprom_update_dword((uint32_t*)EEPROM_JOB_ID, 0); } //! @brief Get default sheet name for index diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 2590d0f2..df91e2b6 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -324,6 +324,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | 0x0D11 3345 | float | EEPROM_UVLO_ACCELL | ??? | ff ff ff ffh | Power panic saved normal acceleration | ??? | D3 Ax0d11 C4 | 0x0D0D 3341 | float | EEPROM_UVLO_RETRACT_ACCELL | ??? | ff ff ff ffh | Power panic saved retract acceleration | ??? | D3 Ax0d0d C4 | 0x0D09 3337 | float | EEPROM_UVLO_TRAVEL_ACCELL | ??? | ff ff ff ffh | Power panic saved travel acceleration | ??? | D3 Ax0d09 C4 +| 0x0D05 3333 | uint32_t | EEPROM_JOB_ID | ??? | 00 00 00 00h | Job ID used by host software | D3 only | D3 Ax0d05 C4 | Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: @@ -337,6 +338,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP #define EEPROM_EMPTY_VALUE 0xFF #define EEPROM_EMPTY_VALUE16 0xFFFF +#define EEPROM_EMPTY_VALUE32 0xFFFFFFFFl // The total size of the EEPROM is // 4096 for the Atmega2560 #define EEPROM_TOP 4096 @@ -534,8 +536,10 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE); #define EEPROM_UVLO_RETRACT_ACCELL (EEPROM_UVLO_ACCELL-4) // float #define EEPROM_UVLO_TRAVEL_ACCELL (EEPROM_UVLO_RETRACT_ACCELL-4) // float +#define EEPROM_JOB_ID (EEPROM_UVLO_TRAVEL_ACCELL-4) //uint32_t + //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items. -#define EEPROM_LAST_ITEM EEPROM_UVLO_TRAVEL_ACCELL +#define EEPROM_LAST_ITEM EEPROM_JOB_ID // !!!!! // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!! // !!!!! diff --git a/Firmware/language.c b/Firmware/language.c index 368997cf..01a39652 100644 --- a/Firmware/language.c +++ b/Firmware/language.c @@ -7,9 +7,9 @@ #include "Configuration.h" #include "pins.h" -#ifdef W25X20CL -#include "w25x20cl.h" -#endif //W25X20CL +#ifdef XFLASH +#include "xflash.h" +#endif //XFLASH // Currently active language selection. uint8_t lang_selected = 0; @@ -54,7 +54,7 @@ uint8_t lang_select(uint8_t lang) lang_table = 0; lang_selected = lang; } -#ifdef W25X20CL +#ifdef XFLASH if (lang_get_code(lang) == lang_get_code(LANG_ID_SEC)) lang = LANG_ID_SEC; if (lang == LANG_ID_SEC) //current secondary language { @@ -68,7 +68,7 @@ uint8_t lang_select(uint8_t lang) } } } -#else //W25X20CL +#else //XFLASH if (lang == LANG_ID_SEC) { uint16_t table = _SEC_LANG_TABLE; @@ -82,7 +82,7 @@ uint8_t lang_select(uint8_t lang) } } } -#endif //W25X20CL +#endif //XFLASH if (lang_selected == lang) { eeprom_update_byte((unsigned char*)EEPROM_LANG, lang_selected); @@ -107,19 +107,19 @@ uint8_t lang_get_count() { if (pgm_read_dword(((uint32_t*)(_PRI_LANG_SIGNATURE))) == 0xffffffff) return 1; //signature not set - only primary language will be available -#ifdef W25X20CL - W25X20CL_SPI_ENTER(); +#ifdef XFLASH + XFLASH_SPI_ENTER(); uint8_t count = 2; //count = 1+n (primary + secondary + all in xflash) uint32_t addr = 0x00000; //start of xflash lang_table_header_t header; //table header structure while (1) { - w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash + xflash_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash if (header.magic != LANG_MAGIC) break; //break if magic not valid addr += header.size; //calc address of next table count++; //inc counter } -#else //W25X20CL +#else //XFLASH uint16_t table = _SEC_LANG_TABLE; uint8_t count = 1; //count = 1 (primary) while (pgm_read_dword(((uint32_t*)table)) == LANG_MAGIC) //magic valid @@ -127,14 +127,14 @@ uint8_t lang_get_count() table += pgm_read_word((uint16_t*)(table + 4)); count++; } -#endif //W25X20CL +#endif //XFLASH return count; } uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* offset) { if (lang == LANG_ID_PRI) return 0; //primary lang not supported for this function -#ifdef W25X20CL +#ifdef XFLASH if (lang == LANG_ID_SEC) { uint16_t ui = _SEC_LANG_TABLE; //table pointer @@ -142,18 +142,18 @@ uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* off if (offset) *offset = ui; return (header->magic == LANG_MAGIC)?1:0; //return 1 if magic valid } - W25X20CL_SPI_ENTER(); + XFLASH_SPI_ENTER(); uint32_t addr = 0x00000; //start of xflash lang--; while (1) { - w25x20cl_rd_data(addr, (uint8_t*)(header), sizeof(lang_table_header_t)); //read table header from xflash + xflash_rd_data(addr, (uint8_t*)(header), sizeof(lang_table_header_t)); //read table header from xflash if (header->magic != LANG_MAGIC) break; //break if not valid if (offset) *offset = addr; if (--lang == 0) return 1; addr += header->size; //calc address of next table } -#else //W25X20CL +#else //XFLASH if (lang == LANG_ID_SEC) { uint16_t ui = _SEC_LANG_TABLE; //table pointer @@ -161,32 +161,32 @@ uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* off if (offset) *offset = ui; return (header->magic == LANG_MAGIC)?1:0; //return 1 if magic valid } -#endif //W25X20CL +#endif //XFLASH return 0; } uint16_t lang_get_code(uint8_t lang) { if (lang == LANG_ID_PRI) return LANG_CODE_EN; //primary lang = EN -#ifdef W25X20CL +#ifdef XFLASH if (lang == LANG_ID_SEC) { uint16_t ui = _SEC_LANG_TABLE; //table pointer if (pgm_read_dword(((uint32_t*)(ui + 0))) != LANG_MAGIC) return LANG_CODE_XX; //magic not valid return pgm_read_word(((uint32_t*)(ui + 10))); //return lang code from progmem } - W25X20CL_SPI_ENTER(); + XFLASH_SPI_ENTER(); uint32_t addr = 0x00000; //start of xflash lang_table_header_t header; //table header structure lang--; while (1) { - w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash + xflash_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash if (header.magic != LANG_MAGIC) break; //break if not valid if (--lang == 0) return header.code; addr += header.size; //calc address of next table } -#else //W25X20CL +#else //XFLASH uint16_t table = _SEC_LANG_TABLE; uint8_t count = 1; //count = 1 (primary) while (pgm_read_dword((uint32_t*)table) == LANG_MAGIC) //magic valid @@ -195,7 +195,7 @@ uint16_t lang_get_code(uint8_t lang) table += pgm_read_word((uint16_t*)(table + 4)); count++; } -#endif //W25X20CL +#endif //XFLASH return LANG_CODE_XX; } diff --git a/Firmware/mesh_bed_calibration.cpp b/Firmware/mesh_bed_calibration.cpp index b4490e93..22a8d7b9 100644 --- a/Firmware/mesh_bed_calibration.cpp +++ b/Firmware/mesh_bed_calibration.cpp @@ -1,4 +1,3 @@ -#include "Marlin.h" #include "Configuration.h" #include "ConfigurationStore.h" #include "language.h" @@ -1065,7 +1064,7 @@ error: } #ifdef NEW_XYZCAL -bool xyzcal_find_bed_induction_sensor_point_xy(); +BedSkewOffsetDetectionResultType xyzcal_find_bed_induction_sensor_point_xy(); #endif //NEW_XYZCAL // Search around the current_position[X,Y], // look for the induction sensor response. @@ -1081,7 +1080,7 @@ bool xyzcal_find_bed_induction_sensor_point_xy(); #endif //HEATBED_V2 #ifdef HEATBED_V2 -bool find_bed_induction_sensor_point_xy(int +BedSkewOffsetDetectionResultType find_bed_induction_sensor_point_xy(int #if !defined (NEW_XYZCAL) && defined (SUPPORT_VERBOSITY) verbosity_level #endif @@ -1137,7 +1136,7 @@ bool find_bed_induction_sensor_point_xy(int // go_xyz(current_position[X_AXIS], current_position[Y_AXIS], MESH_HOME_Z_SEARCH, homing_feedrate[Z_AXIS]/60); go_xyz(x0, y0, current_position[Z_AXIS], feedrate); - // Continously lower the Z axis. + // Continuously lower the Z axis. endstops_hit_on_purpose(); enable_z_endstop(true); bool direction = false; @@ -1335,7 +1334,7 @@ bool find_bed_induction_sensor_point_xy(int #endif //NEW_XYZCAL } #else //HEATBED_V2 -bool find_bed_induction_sensor_point_xy(int verbosity_level) +BedSkewOffsetDetectionResultType find_bed_induction_sensor_point_xy(int verbosity_level) { #ifdef NEW_XYZCAL return xyzcal_find_bed_induction_sensor_point_xy(); @@ -1531,7 +1530,9 @@ bool find_bed_induction_sensor_point_xy(int verbosity_level) } enable_z_endstop(false); - return found; + if (found) + return BED_SKEW_OFFSET_DETECTION_POINT_FOUND; + return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND; #endif //NEW_XYZCAL } @@ -2238,9 +2239,15 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level // Collect the rear 2x3 points. current_position[Z_AXIS] = MESH_HOME_Z_SEARCH + FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP * iteration * 0.3; - for (int k = 0; k < 4; ++k) { - // Don't let the manage_inactivity() function remove power from the motors. - refresh_cmd_timeout(); + + /// Retry point scanning if a point with bad data appears. + /// Bad data could be cause by "cold" sensor. + /// This behavior vanishes after few point scans so retry will help. + for (int retries = 0; retries <= 1; ++retries) { + bool retry = false; + for (int k = 0; k < 4; ++k) { + // Don't let the manage_inactivity() function remove power from the motors. + refresh_cmd_timeout(); #ifdef MESH_BED_CALIBRATION_SHOW_LCD lcd_set_cursor(0, next_line); lcd_print(k + 1); @@ -2304,8 +2311,19 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level if (verbosity_level >= 10) delay_keep_alive(3000); #endif // SUPPORT_VERBOSITY - if (!find_bed_induction_sensor_point_xy(verbosity_level)) - return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND; + + BedSkewOffsetDetectionResultType result; + result = find_bed_induction_sensor_point_xy(verbosity_level); + switch(result){ + case BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND: + return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND; + case BED_SKEW_OFFSET_DETECTION_POINT_SCAN_FAILED: + retry = true; + break; + default: + break; + } + #ifndef NEW_XYZCAL #ifndef HEATBED_V2 @@ -2380,6 +2398,9 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level } #endif // SUPPORT_VERBOSITY } + if (!retry) + break; + } DBG(_n("All 4 calibration points found.\n")); delay_keep_alive(0); //manage_heater, reset watchdog, manage inactivity diff --git a/Firmware/mesh_bed_calibration.h b/Firmware/mesh_bed_calibration.h index 7ca93c95..c539d4b5 100644 --- a/Firmware/mesh_bed_calibration.h +++ b/Firmware/mesh_bed_calibration.h @@ -1,5 +1,6 @@ -#ifndef MESH_BED_CALIBRATION_H -#define MESH_BED_CALIBRATION_H +#pragma once + +#include "Marlin.h" #define BED_ZERO_REF_X (- 22.f + X_PROBE_OFFSET_FROM_EXTRUDER) // -22 + 23 = 1 #define BED_ZERO_REF_Y (- 0.6f + Y_PROBE_OFFSET_FROM_EXTRUDER + 4.f) // -0.6 + 5 + 4 = 8.4 @@ -145,11 +146,6 @@ inline bool world2machine_clamp(float &x, float &y) machine2world(tmpx, tmpy, x, y); return clamped; } - -bool find_bed_induction_sensor_point_z(float minimum_z = -10.f, uint8_t n_iter = 3, int verbosity_level = 0); -bool find_bed_induction_sensor_point_xy(int verbosity_level = 0); -void go_home_with_z_lift(); - /** * @brief Bed skew and offest detection result * @@ -159,8 +155,10 @@ void go_home_with_z_lift(); enum BedSkewOffsetDetectionResultType { // Detection failed, some point was not found. + BED_SKEW_OFFSET_DETECTION_POINT_FOUND = 0, //!< Point found BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND = -1, //!< Point not found. BED_SKEW_OFFSET_DETECTION_FITTING_FAILED = -2, //!< Fitting failed + BED_SKEW_OFFSET_DETECTION_POINT_SCAN_FAILED = -3, //!< Point scan failed, try again // Detection finished with success. BED_SKEW_OFFSET_DETECTION_PERFECT = 0, //!< Perfect. @@ -168,6 +166,10 @@ enum BedSkewOffsetDetectionResultType { BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME = 2 //!< Extremely skewed. }; +bool find_bed_induction_sensor_point_z(float minimum_z = -10.f, uint8_t n_iter = 3, int verbosity_level = 0); +BedSkewOffsetDetectionResultType find_bed_induction_sensor_point_xy(int verbosity_level = 0); +void go_home_with_z_lift(); + extern BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level, uint8_t &too_far_mask); #ifndef NEW_XYZCAL extern BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8_t verbosity_level, uint8_t &too_far_mask); @@ -213,4 +215,3 @@ extern void mbl_settings_init(); extern bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy, uint8_t meas_points, bool zigzag); extern void mbl_interpolation(uint8_t meas_points); -#endif /* MESH_BED_CALIBRATION_H */ diff --git a/Firmware/optiboot_w25x20cl.h b/Firmware/optiboot_w25x20cl.h deleted file mode 100644 index 95c6465f..00000000 --- a/Firmware/optiboot_w25x20cl.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef OPTIBOOT_W25X20CL_H -#define OPTIBOOT_W25X20CL_H - -extern uint8_t optiboot_w25x20cl_enter(); - -#endif /* OPTIBOOT_W25X20CL_H */ diff --git a/Firmware/optiboot_w25x20cl.cpp b/Firmware/optiboot_xflash.cpp similarity index 93% rename from Firmware/optiboot_w25x20cl.cpp rename to Firmware/optiboot_xflash.cpp index ed38b299..fb1f8075 100644 --- a/Firmware/optiboot_w25x20cl.cpp +++ b/Firmware/optiboot_xflash.cpp @@ -4,7 +4,7 @@ // Licence GLP 2 or later. #include "Marlin.h" -#include "w25x20cl.h" +#include "xflash.h" #include "stk500.h" #include "bootapp.h" #include @@ -16,14 +16,14 @@ static unsigned const int __attribute__((section(".version"))) optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER; #if 0 -#define W25X20CL_SIGNATURE_0 9 -#define W25X20CL_SIGNATURE_1 8 -#define W25X20CL_SIGNATURE_2 7 +#define XFLASH_SIGNATURE_0 9 +#define XFLASH_SIGNATURE_1 8 +#define XFLASH_SIGNATURE_2 7 #else //FIXME this is a signature of ATmega2560! -#define W25X20CL_SIGNATURE_0 0x1E -#define W25X20CL_SIGNATURE_1 0x98 -#define W25X20CL_SIGNATURE_2 0x01 +#define XFLASH_SIGNATURE_0 0x1E +#define XFLASH_SIGNATURE_1 0x98 +#define XFLASH_SIGNATURE_2 0x01 #endif #define RECV_READY ((UCSR0A & _BV(RXC0)) != 0) @@ -78,7 +78,7 @@ extern struct block_t *block_buffer; //! @brief Enter an STK500 compatible Optiboot boot loader waiting for flashing the languages to an external flash memory. //! @return 1 if "start\n" was not sent. Optiboot was skipped //! @return 0 if "start\n" was sent. Optiboot ran normally. No need to send "start\n" in setup() -uint8_t optiboot_w25x20cl_enter() +uint8_t optiboot_xflash_enter() { // Make sure to check boot_app_magic as well. Since these bootapp flags are located right in the middle of the stack, // they can be unintentionally changed. As a workaround to the language upload problem, do not only check for one bit if it's set, @@ -154,7 +154,7 @@ uint8_t optiboot_w25x20cl_enter() } spi_init(); - w25x20cl_init(); + xflash_init(); wdt_disable(); /* Forever loop: exits by causing WDT reset */ @@ -254,16 +254,16 @@ uint8_t optiboot_w25x20cl_enter() // During a single bootloader run, only erase a 64kB block once. // An 8bit bitmask 'pages_erased' covers 512kB of FLASH memory. if ((address == 0) && (pages_erased & (1 << (addr >> 16))) == 0) { - w25x20cl_wait_busy(); - w25x20cl_enable_wr(); - w25x20cl_block64_erase(addr); + xflash_wait_busy(); + xflash_enable_wr(); + xflash_block64_erase(addr); pages_erased |= (1 << (addr >> 16)); } - w25x20cl_wait_busy(); - w25x20cl_enable_wr(); - w25x20cl_page_program(addr, buff, savelength); - w25x20cl_wait_busy(); - w25x20cl_disable_wr(); + xflash_wait_busy(); + xflash_enable_wr(); + xflash_page_program(addr, buff, savelength); + xflash_wait_busy(); + xflash_disable_wr(); } } /* Read memory block mode, length is big endian. */ @@ -279,8 +279,8 @@ uint8_t optiboot_w25x20cl_enter() // Read the destination type. It should always be 'F' as flash. It is not checked. (void)getch(); verifySpace(); - w25x20cl_wait_busy(); - w25x20cl_rd_data(addr, buff, length); + xflash_wait_busy(); + xflash_rd_data(addr, buff, length); for (i = 0; i < length; ++ i) putch(buff[i]); } @@ -288,9 +288,9 @@ uint8_t optiboot_w25x20cl_enter() else if(ch == STK_READ_SIGN) { // READ SIGN - return what Avrdude wants to hear verifySpace(); - putch(W25X20CL_SIGNATURE_0); - putch(W25X20CL_SIGNATURE_1); - putch(W25X20CL_SIGNATURE_2); + putch(XFLASH_SIGNATURE_0); + putch(XFLASH_SIGNATURE_1); + putch(XFLASH_SIGNATURE_2); } else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */ // Adaboot no-wait mod diff --git a/Firmware/optiboot_xflash.h b/Firmware/optiboot_xflash.h new file mode 100644 index 00000000..453c9e00 --- /dev/null +++ b/Firmware/optiboot_xflash.h @@ -0,0 +1,6 @@ +#ifndef OPTIBOOT_XFLASH_H +#define OPTIBOOT_XFLASH_H + +extern uint8_t optiboot_xflash_enter(); + +#endif /* OPTIBOOT_XFLASH_H */ diff --git a/Firmware/pins_Einsy_1_0.h b/Firmware/pins_Einsy_1_0.h index 70660bca..b3841a59 100755 --- a/Firmware/pins_Einsy_1_0.h +++ b/Firmware/pins_Einsy_1_0.h @@ -15,9 +15,11 @@ #define AMBIENT_THERMISTOR #define PINDA_THERMISTOR -#define W25X20CL // external 256kB flash +#define XFLASH // external 256kB flash #define BOOTAPP // bootloader support +#define XFLASH_PIN_CS 32 + #define X_TMC2130_CS 41 #define X_TMC2130_DIAG 64 // !!! changed from 40 (EINY03) #define X_STEP_PIN 37 diff --git a/Firmware/tmc2130.cpp b/Firmware/tmc2130.cpp index 3f682690..480efb2b 100755 --- a/Firmware/tmc2130.cpp +++ b/Firmware/tmc2130.cpp @@ -68,8 +68,9 @@ uint8_t tmc2130_sg_diag_mask = 0x00; uint8_t tmc2130_sg_crash = 0; uint16_t tmc2130_sg_err[4] = {0, 0, 0, 0}; uint16_t tmc2130_sg_cnt[4] = {0, 0, 0, 0}; +#ifdef DEBUG_CRASHDET_COUNTERS bool tmc2130_sg_change = false; - +#endif bool skip_debug_msg = false; @@ -255,7 +256,9 @@ void tmc2130_st_isr() if (tmc2130_sg_cnt[axis] < tmc2130_sg_err[axis]) { tmc2130_sg_cnt[axis] = tmc2130_sg_err[axis]; +#ifdef DEBUG_CRASHDET_COUNTERS tmc2130_sg_change = true; +#endif uint8_t sg_thr = 64; // if (axis == Y_AXIS) sg_thr = 64; if (tmc2130_sg_err[axis] >= sg_thr) @@ -409,7 +412,9 @@ void tmc2130_check_overtemp() } checktime = _millis(); +#ifdef DEBUG_CRASHDET_COUNTERS tmc2130_sg_change = true; +#endif } #ifdef DEBUG_CRASHDET_COUNTERS if (tmc2130_sg_change) diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index e1d89c3f..3e765a5c 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -510,9 +510,9 @@ void lcdui_print_time(void) //if remaining print time estimation is available print it else print elapsed time int chars = 0; if (PRINTER_ACTIVE) { - uint16_t print_t = 0; - uint16_t print_tr = 0; - uint16_t print_tc = 0; + uint16_t print_t = PRINT_TIME_REMAINING_INIT; + uint16_t print_tr = PRINT_TIME_REMAINING_INIT; + uint16_t print_tc = PRINT_TIME_REMAINING_INIT; char suff = ' '; char suff_doubt = ' '; @@ -542,12 +542,12 @@ void lcdui_print_time(void) clock_interval++; - if (print_tc != 0 && clock_interval > CLOCK_INTERVAL_TIME) { + if (print_tc != PRINT_TIME_REMAINING_INIT && clock_interval > CLOCK_INTERVAL_TIME) { print_t = print_tc; suff = 'C'; } else //#endif //CLOCK_INTERVAL_TIME - if (print_tr != 0) { + if (print_tr != PRINT_TIME_REMAINING_INIT) { print_t = print_tr; suff = 'R'; } else @@ -4361,7 +4361,7 @@ void menu_setlang(unsigned char lang) } #ifdef COMMUNITY_LANG_SUPPORT -#ifdef W25X20CL +#ifdef XFLASH static void lcd_community_language_menu() { MENU_BEGIN(); @@ -4375,7 +4375,7 @@ static void lcd_community_language_menu() } MENU_END(); } -#endif //W25X20CL +#endif //XFLASH #endif //COMMUNITY_LANG_SUPPORT && W52X20CL @@ -4390,7 +4390,7 @@ static void lcd_language_menu() return; } uint8_t cnt = lang_get_count(); -#ifdef W25X20CL +#ifdef XFLASH if (cnt == 2) //display secondary language in case of clear xflash { if (menu_item_text_P(lang_get_name_by_code(lang_get_code(1)))) @@ -4401,9 +4401,9 @@ static void lcd_language_menu() } else for (int i = 2; i < 8; i++) //skip seconday language - solved in lang_select (MK3) 'i < 8' for 7 official languages -#else //W25X20CL +#else //XFLASH for (int i = 1; i < cnt; i++) //all seconday languages (MK2/25) -#endif //W25X20CL +#endif //XFLASH if (menu_item_text_P(lang_get_name_by_code(lang_get_code(i)))) { menu_setlang(i); @@ -4411,9 +4411,9 @@ static void lcd_language_menu() } #ifdef COMMUNITY_LANG_SUPPORT -#ifdef W25X20CL +#ifdef XFLASH MENU_ITEM_SUBMENU_P(_T(MSG_COMMUNITY_MADE), lcd_community_language_menu); ////MSG_COMMUNITY_MADE c=18 -#endif //W25X20CL +#endif //XFLASH #endif //COMMUNITY_LANG_SUPPORT && W52X20CL MENU_END(); @@ -6323,15 +6323,15 @@ unsigned char lcd_choose_color() { } -#include "w25x20cl.h" +#include "xflash.h" #ifdef LCD_TEST static void lcd_test_menu() { - W25X20CL_SPI_ENTER(); - w25x20cl_enable_wr(); - w25x20cl_chip_erase(); - w25x20cl_disable_wr(); + XFLASH_SPI_ENTER(); + xflash_enable_wr(); + xflash_chip_erase(); + xflash_disable_wr(); } #endif //LCD_TEST @@ -6672,7 +6672,7 @@ static void lcd_main_menu() } MENU_ITEM_SUBMENU_P(_i("Support"), lcd_support_menu);////MSG_SUPPORT #ifdef LCD_TEST - MENU_ITEM_SUBMENU_P(_i("W25x20CL init"), lcd_test_menu);////MSG_SUPPORT + MENU_ITEM_SUBMENU_P(_i("XFLASH init"), lcd_test_menu);////MSG_SUPPORT #endif //LCD_TEST MENU_END(); diff --git a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h index 2c62f2fd..8caaeb32 100644 --- a/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h @@ -159,7 +159,7 @@ //#define DEBUG_BUILD //#define DEBUG_SEC_LANG //secondary language debug output at startup -//#define DEBUG_W25X20CL //debug external spi flash +//#define DEBUG_XFLASH //debug external spi flash #ifdef DEBUG_BUILD //#define _NO_ASM #define DEBUG_DCODES //D codes diff --git a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h index d74d75d5..e9619afc 100644 --- a/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h +++ b/Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h @@ -161,7 +161,7 @@ //#define DEBUG_BUILD //#define DEBUG_SEC_LANG //secondary language debug output at startup -//#define DEBUG_W25X20CL //debug external spi flash +//#define DEBUG_XFLASH //debug external spi flash #ifdef DEBUG_BUILD //#define _NO_ASM #define DEBUG_DCODES //D codes diff --git a/Firmware/w25x20cl.h b/Firmware/w25x20cl.h deleted file mode 100644 index 10aaaf2c..00000000 --- a/Firmware/w25x20cl.h +++ /dev/null @@ -1,44 +0,0 @@ -//w25x20cl.h -#ifndef _W25X20CL_H -#define _W25X20CL_H - -#include -#include "config.h" -#include "spi.h" - - - -#define W25X20CL_STATUS_BUSY 0x01 -#define W25X20CL_STATUS_WEL 0x02 -#define W25X20CL_STATUS_BP0 0x04 -#define W25X20CL_STATUS_BP1 0x08 -#define W25X20CL_STATUS_TB 0x20 -#define W25X20CL_STATUS_SRP 0x80 - -#define W25X20CL_SPI_ENTER() spi_setup(W25X20CL_SPCR, W25X20CL_SPSR) - -#if defined(__cplusplus) -extern "C" { -#endif //defined(__cplusplus) - - -extern int8_t w25x20cl_init(void); -extern void w25x20cl_enable_wr(void); -extern void w25x20cl_disable_wr(void); -extern uint8_t w25x20cl_rd_status_reg(void); -extern void w25x20cl_wr_status_reg(uint8_t val); -extern void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt); -extern void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt); -extern void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt); -extern void w25x20cl_sector_erase(uint32_t addr); -extern void w25x20cl_block32_erase(uint32_t addr); -extern void w25x20cl_block64_erase(uint32_t addr); -extern void w25x20cl_chip_erase(void); -extern void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt); -extern void w25x20cl_rd_uid(uint8_t* uid); -extern void w25x20cl_wait_busy(void); - -#if defined(__cplusplus) -} -#endif //defined(__cplusplus) -#endif //_W25X20CL_H diff --git a/Firmware/w25x20cl.c b/Firmware/xflash.c similarity index 68% rename from Firmware/w25x20cl.c rename to Firmware/xflash.c index 40d183f1..e9d894a5 100644 --- a/Firmware/w25x20cl.c +++ b/Firmware/xflash.c @@ -1,13 +1,18 @@ -//w25x20cl.c +//xflash.c -#include "w25x20cl.h" +#include "xflash.h" #include #include #include "spi.h" #include "fastio.h" -#define _MFRID 0xEF -#define _DEVID 0x11 +#ifdef XFLASH + +#define _MFRID_W25X20CL 0xEF +#define _DEVID_W25X20CL 0x11 + +#define _MFRID_GD25Q20C 0xC8 +#define _DEVID_GD25Q20C 0x11 #define _CMD_ENABLE_WR 0x06 #define _CMD_ENABLE_WR_VSR 0x50 @@ -31,8 +36,8 @@ #define _CMD_JEDEC_ID 0x9f #define _CMD_RD_UID 0x4b -#define _CS_LOW() WRITE(W25X20CL_PIN_CS, 0) -#define _CS_HIGH() WRITE(W25X20CL_PIN_CS, 1) +#define _CS_LOW() WRITE(XFLASH_PIN_CS, 0) +#define _CS_HIGH() WRITE(XFLASH_PIN_CS, 1) //#define _SPI_TX swspi_tx //#define _SPI_RX swspi_rx @@ -40,33 +45,33 @@ #define _SPI_RX() spi_txrx(0xff) -int w25x20cl_mfrid_devid(void); +int xflash_mfrid_devid(void); -int8_t w25x20cl_init(void) +int8_t xflash_init(void) { _CS_HIGH(); - SET_OUTPUT(W25X20CL_PIN_CS); - W25X20CL_SPI_ENTER(); - if (!w25x20cl_mfrid_devid()) return 0; + SET_OUTPUT(XFLASH_PIN_CS); + XFLASH_SPI_ENTER(); + if (!xflash_mfrid_devid()) return 0; return 1; } -void w25x20cl_enable_wr(void) +void xflash_enable_wr(void) { _CS_LOW(); _SPI_TX(_CMD_ENABLE_WR); // send command 0x06 _CS_HIGH(); } -void w25x20cl_disable_wr(void) +void xflash_disable_wr(void) { _CS_LOW(); _SPI_TX(_CMD_DISABLE_WR); // send command 0x04 _CS_HIGH(); } -uint8_t w25x20cl_rd_status_reg(void) +uint8_t xflash_rd_status_reg(void) { _CS_LOW(); _SPI_TX(_CMD_RD_STATUS_REG); // send command 0x90 @@ -75,6 +80,7 @@ uint8_t w25x20cl_rd_status_reg(void) return val; } +#if 0 void w25x20cl_wr_status_reg(uint8_t val) { _CS_LOW(); @@ -82,8 +88,9 @@ void w25x20cl_wr_status_reg(uint8_t val) _SPI_TX(val); // send value _CS_HIGH(); } +#endif -void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt) +void xflash_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt) { _CS_LOW(); _SPI_TX(_CMD_RD_DATA); // send command 0x03 @@ -95,7 +102,7 @@ void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt) _CS_HIGH(); } -void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt) +void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt) { _CS_LOW(); _SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02 @@ -107,7 +114,7 @@ void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt) _CS_HIGH(); } -void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt) +void xflash_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt) { _CS_LOW(); _SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02 @@ -119,7 +126,7 @@ void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt) _CS_HIGH(); } -void w25x20cl_erase(uint8_t cmd, uint32_t addr) +void xflash_erase(uint8_t cmd, uint32_t addr) { _CS_LOW(); _SPI_TX(cmd); // send command 0x20 @@ -129,22 +136,22 @@ void w25x20cl_erase(uint8_t cmd, uint32_t addr) _CS_HIGH(); } -void w25x20cl_sector_erase(uint32_t addr) +void xflash_sector_erase(uint32_t addr) { - return w25x20cl_erase(_CMD_SECTOR_ERASE, addr); + return xflash_erase(_CMD_SECTOR_ERASE, addr); } -void w25x20cl_block32_erase(uint32_t addr) +void xflash_block32_erase(uint32_t addr) { - return w25x20cl_erase(_CMD_BLOCK32_ERASE, addr); + return xflash_erase(_CMD_BLOCK32_ERASE, addr); } -void w25x20cl_block64_erase(uint32_t addr) +void xflash_block64_erase(uint32_t addr) { - return w25x20cl_erase(_CMD_BLOCK64_ERASE, addr); + return xflash_erase(_CMD_BLOCK64_ERASE, addr); } -void w25x20cl_chip_erase(void) +void xflash_chip_erase(void) { _CS_LOW(); _SPI_TX(_CMD_CHIP_ERASE); // send command 0xc7 @@ -152,33 +159,37 @@ void w25x20cl_chip_erase(void) } -void w25x20cl_rd_uid(uint8_t* uid) +void xflash_rd_uid(uint8_t* uid) { _CS_LOW(); _SPI_TX(_CMD_RD_UID); // send command 0x4b uint8_t cnt = 4; // 4 dummy bytes - while (cnt--) // receive dummy bytes - _SPI_RX(); + while (cnt--) // transmit dummy bytes + _SPI_TX(0x00); cnt = 8; // 8 bytes UID while (cnt--) // receive UID uid[7 - cnt] = _SPI_RX(); _CS_HIGH(); } -int w25x20cl_mfrid_devid(void) +int xflash_mfrid_devid(void) { _CS_LOW(); _SPI_TX(_CMD_MFRID_DEVID); // send command 0x90 uint8_t cnt = 3; // 3 address bytes while (cnt--) // send address bytes _SPI_TX(0x00); - uint8_t w25x20cl_mfrid = _SPI_RX(); // receive mfrid - uint8_t w25x20cl_devid = _SPI_RX(); // receive devid + uint8_t xflash_mfrid = _SPI_RX(); // receive mfrid + uint8_t xflash_devid = _SPI_RX(); // receive devid _CS_HIGH(); - return ((w25x20cl_mfrid == _MFRID) && (w25x20cl_devid == _DEVID)); + return + ((xflash_mfrid == _MFRID_W25X20CL) && (xflash_devid == _DEVID_W25X20CL)) || + ((xflash_mfrid == _MFRID_GD25Q20C) && (xflash_devid == _DEVID_GD25Q20C)); } -void w25x20cl_wait_busy(void) +void xflash_wait_busy(void) { - while (w25x20cl_rd_status_reg() & W25X20CL_STATUS_BUSY) ; + while (xflash_rd_status_reg() & XFLASH_STATUS_BUSY) ; } + +#endif //XFLASH diff --git a/Firmware/xflash.h b/Firmware/xflash.h new file mode 100644 index 00000000..c9ad5275 --- /dev/null +++ b/Firmware/xflash.h @@ -0,0 +1,50 @@ +//xflash.h +#ifndef _XFLASH_H +#define _XFLASH_H + +#include +#include "config.h" +#include "spi.h" + + + +#define XFLASH_STATUS_BUSY 0x01 +#define XFLASH_STATUS_WEL 0x02 +#define XFLASH_STATUS_BP0 0x04 +#define XFLASH_STATUS_BP1 0x08 +#define XFLASH_STATUS_TB 0x20 +#define XFLASH_STATUS_SRP 0x80 + +#define XFLASH_SPI_RATE 0 // fosc/4 = 4MHz +#define XFLASH_SPCR SPI_SPCR(XFLASH_SPI_RATE, 1, 1, 1, 0) +#define XFLASH_SPSR SPI_SPSR(XFLASH_SPI_RATE) + +#define XFLASH_SPI_ENTER() spi_setup(XFLASH_SPCR, XFLASH_SPSR) + +#if defined(__cplusplus) +extern "C" { +#endif //defined(__cplusplus) + + +extern int8_t xflash_init(void); +extern void xflash_enable_wr(void); +extern void xflash_disable_wr(void); +extern uint8_t xflash_rd_status_reg(void); +#if 0 +extern void w25x20cl_wr_status_reg(uint8_t val); +#endif +extern void xflash_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt); +extern void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt); +extern void xflash_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt); +extern void xflash_sector_erase(uint32_t addr); +extern void xflash_block32_erase(uint32_t addr); +extern void xflash_block64_erase(uint32_t addr); +extern void xflash_chip_erase(void); +extern void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt); +extern void xflash_rd_uid(uint8_t* uid); +extern void xflash_wait_busy(void); + +#if defined(__cplusplus) +} +#endif //defined(__cplusplus) +#endif //_XFLASH_H diff --git a/Firmware/xyzcal.cpp b/Firmware/xyzcal.cpp index 9293c2e8..ea92359c 100644 --- a/Firmware/xyzcal.cpp +++ b/Firmware/xyzcal.cpp @@ -837,7 +837,7 @@ void dynamic_circle(uint8_t *matrix_32x32, float &x, float &y, float &r, uint8_t for (int8_t i = iterations; i > 0; --i){ //@size=128B - DBG(_n(" [%f, %f][%f] circle\n"), x, y, r); + // DBG(_n(" [%f, %f][%f] circle\n"), x, y, r); /// read points on the circle for (uint8_t p = 0; p < num_points; ++p){ @@ -904,12 +904,42 @@ uint8_t find_patterns(uint8_t *matrix32, uint16_t *pattern08, uint16_t *pattern1 return match10; } +/// Scan should include normal data. +/// If it's too extreme (00, FF) it could be caused by biased sensor. +/// \return true if data looks normal +bool check_scan(uint8_t *matrix32){ + /// magic constants that define normality + const int16_t threshold_total = 900; + const int threshold_extreme = 50; + + int16_t mins = 0; + int16_t maxs = 0; + + for (int16_t i = 0; i < 32*32;++i){ + if (matrix32[i] == 0) { + ++mins; + } else if (matrix32[i] == 0xFF){ + ++maxs; + } + } + const int16_t rest = 1024 - mins - maxs; + + if (mins + maxs > threshold_total + && mins > threshold_extreme + && maxs > threshold_extreme + && mins > rest + && maxs > rest) + return false; + + return true; +} + /// scans area around the current head location and /// searches for the center of the calibration pin -bool xyzcal_scan_and_process(void){ +BedSkewOffsetDetectionResultType xyzcal_scan_and_process(){ //@size=44 - DBG(_n("sizeof(block_buffer)=%d\n"), sizeof(block_t)*BLOCK_BUFFER_SIZE); - bool ret = false; + // DBG(_n("sizeof(block_buffer)=%d\n"), sizeof(block_t)*BLOCK_BUFFER_SIZE); + BedSkewOffsetDetectionResultType ret = BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND; int16_t x = _X; int16_t y = _Y; const int16_t z = _Z; @@ -925,6 +955,8 @@ bool xyzcal_scan_and_process(void){ xyzcal_scan_pixels_32x32_Zhop(x, y, z, 2400, 200, matrix32); print_image(matrix32); + if (!check_scan(matrix32)) + return BED_SKEW_OFFSET_DETECTION_POINT_SCAN_FAILED; /// SEARCH FOR BINARY CIRCLE uint8_t uc = 0; @@ -955,7 +987,7 @@ bool xyzcal_scan_and_process(void){ x = round_to_i16(xf); y = round_to_i16(yf); xyzcal_lineXYZ_to(x, y, z, 200, 0); - ret = true; + ret = BED_SKEW_OFFSET_DETECTION_POINT_FOUND; } /// wipe buffer @@ -964,11 +996,11 @@ bool xyzcal_scan_and_process(void){ return ret; } -bool xyzcal_find_bed_induction_sensor_point_xy(void){ - bool ret = false; +BedSkewOffsetDetectionResultType xyzcal_find_bed_induction_sensor_point_xy(void){ + BedSkewOffsetDetectionResultType ret = BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND; //@size=258 - DBG(_n("xyzcal_find_bed_induction_sensor_point_xy x=%ld y=%ld z=%ld\n"), count_position[X_AXIS], count_position[Y_AXIS], count_position[Z_AXIS]); + // DBG(_n("xyzcal_find_bed_induction_sensor_point_xy x=%ld y=%ld z=%ld\n"), count_position[X_AXIS], count_position[Y_AXIS], count_position[Z_AXIS]); st_synchronize(); xyzcal_meassure_enter(); diff --git a/Firmware/xyzcal.h b/Firmware/xyzcal.h index 348ff3ce..8f908bbe 100644 --- a/Firmware/xyzcal.h +++ b/Firmware/xyzcal.h @@ -1,9 +1,9 @@ //xyzcal.h - xyz calibration with image processing -#ifndef _XYZCAL_H -#define _XYZCAL_H +#pragma once #include +#include "mesh_bed_calibration.h" extern void xyzcal_meassure_enter(void); @@ -17,11 +17,4 @@ extern bool xyzcal_spiral8(int16_t cx, int16_t cy, int16_t z0, int16_t dz, int16 //extern int8_t xyzcal_meassure_pinda_hysterezis(int16_t min_z, int16_t max_z, uint16_t delay_us, uint8_t samples); -extern bool xyzcal_searchZ(void); - -extern bool xyzcal_scan_and_process(void); - -extern bool xyzcal_find_bed_induction_sensor_point_xy(void); - - -#endif //_XYZCAL_H +extern BedSkewOffsetDetectionResultType xyzcal_find_bed_induction_sensor_point_xy();