diff --git a/Firmware/Configuration.h b/Firmware/Configuration.h index d390283f..ef359f39 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.10.0-RC1" -#define FW_COMMIT_NR 4078 +#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 @@ -551,9 +551,10 @@ enum CalibrationStatus // Try to maintain a minimum distance from the bed even when Z is // unknown when doing the following operations -#define MIN_Z_FOR_LOAD 50 -#define MIN_Z_FOR_UNLOAD 50 -#define MIN_Z_FOR_PREHEAT 10 +#define MIN_Z_FOR_LOAD 50 // lcd filament loading or autoload +#define MIN_Z_FOR_UNLOAD 50 // lcd filament unloading +#define MIN_Z_FOR_SWAP 27 // filament change (including M600) +#define MIN_Z_FOR_PREHEAT 10 // lcd preheat #include "Configuration_adv.h" #include "thermistortables.h" 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_main.cpp b/Firmware/Marlin_main.cpp index ab46a894..24266903 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 @@ -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); @@ -3218,12 +3622,12 @@ static T gcode_M600_filament_change_z_shift() #ifdef FILAMENTCHANGE_ZADD static_assert(Z_MAX_POS < (255 - FILAMENTCHANGE_ZADD), "Z-range too high, change the T type from uint8_t to uint16_t"); // avoid floating point arithmetics when not necessary - results in shorter code + T z_shift = T(FILAMENTCHANGE_ZADD); // always move above printout T ztmp = T( current_position[Z_AXIS] ); - T z_shift = 0; - if(ztmp < T(25)){ - z_shift = T(25) - ztmp; // make sure to be at least 25mm above the heat bed - } - return z_shift + T(FILAMENTCHANGE_ZADD); // always move above printout + if((ztmp + z_shift) < T(MIN_Z_FOR_SWAP)){ + z_shift = T(MIN_Z_FOR_SWAP) - ztmp; // make sure to be at least 25mm above the heat bed + } + return z_shift; #else return T(0); #endif @@ -3272,7 +3676,7 @@ static void gcode_M600(bool automatic, float x_position, float y_position, float // Unload filament if (mmu_enabled) extr_unload(); //unload just current filament for multimaterial printers (used also in M702) - else unload_filament(); //unload filament for single material (used also in M702) + else unload_filament(true); //unload filament for single material (used also in M702) //finish moves st_synchronize(); @@ -3559,6 +3963,8 @@ static void extended_capabilities_report() #endif //FANCHECK and TACH_0 or TACH_1 // AUTOREPORT_POSITION (M114) cap_line(PSTR("AUTOREPORT_POSITION"), ENABLED(AUTO_REPORT)); + // EXTENDED_M20 (support for L and T parameters) + cap_line(PSTR("EXTENDED_M20"), 1); //@todo Update RepRap cap } #endif //EXTENDED_CAPABILITIES_REPORT @@ -4013,10 +4419,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 +4936,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 +5149,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 +5254,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,11 +5491,11 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) * v Y-axis */ - case 80: - + case 80: { #ifdef MK1BP break; #endif //MK1BP +<<<<<<< HEAD case_G80: { mesh_bed_leveling_flag = true; @@ -5482,6 +5889,9 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) mesh_bed_run_from_menu = false; lcd_update(2); +======= + gcode_G80(); +>>>>>>> upstream/MK3_3.10.0 } break; @@ -5727,16 +6137,17 @@ if(eSoundMode!=e_SOUND_MODE_SILENT) ### M20 - SD Card file list M20: List SD card #### Usage - M20 [ L ] + M20 [ L | T ] #### Parameters - - `L` - Reports ling filenames instead of just short filenames. Requires host software parsing. + - `T` - Report timestamps as well. The value is one uint32_t encoded as hex. Requires host software parsing (Cap:EXTENDED_M20). + - `L` - Reports long filenames instead of just short filenames. Requires host software parsing (Cap:EXTENDED_M20). */ case 20: KEEPALIVE_STATE(NOT_BUSY); // do not send busy messages during listing. Inhibits the output of manage_heater() SERIAL_PROTOCOLLNRPGM(_N("Begin file list"));////MSG_BEGIN_FILE_LIST - card.ls(code_seen('L')); + card.ls(CardReader::ls_param(code_seen('L'), code_seen('T'))); SERIAL_PROTOCOLLNRPGM(_N("End file list"));////MSG_END_FILE_LIST - break; + break; /*! ### M21 - Init SD card M21: Initialize SD card @@ -6969,19 +7380,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 @@ -10845,8 +11258,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; @@ -10924,8 +11338,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); @@ -11183,11 +11602,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 "); @@ -11199,7 +11613,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; @@ -11236,7 +11654,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]; @@ -11277,10 +11695,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) @@ -11460,7 +11881,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; @@ -11472,7 +11894,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); @@ -11566,6 +11991,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.cpp b/Firmware/cardreader.cpp index 673e88c1..a86c49e1 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -61,10 +61,9 @@ char *createFilename(char *buffer,const dir_t &p) //buffer>12characters +* LS_Count - Add +1 to nrFiles for every file within the parent +* LS_GetFilename - Get the filename of the file indexed by nrFiles +* LS_SerialPrint - Print the full path and size of each file to serial output -+* LS_SerialPrint_LFN - Print the full path, long filename and size of each file to serial output +*/ -void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) { +void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/, LsAction lsAction, ls_param lsParams) { static uint8_t recursionCnt = 0; // RAII incrementer for the recursionCnt class _incrementer @@ -80,8 +79,12 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m for (position = parent.curPosition(); parent.readDir(p, longFilename) > 0; position = parent.curPosition()) { if (recursionCnt > MAX_DIR_DEPTH) return; - else if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // If the entry is a directory and the action is LS_SerialPrint - + uint8_t pn0 = p.name[0]; + if (pn0 == DIR_NAME_FREE) break; + if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue; + if (longFilename[0] == '.') continue; + if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue; + if (DIR_IS_SUBDIR(&p) && lsAction == LS_SerialPrint) { // If the entry is a directory and the action is LS_SerialPrint // Get the short name for the item, which we know is a folder char lfilename[FILENAME_LENGTH]; createFilename(lfilename, p); @@ -99,29 +102,22 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m // Get a new directory object using the full path // and dive recursively into it. - if (lsAction == LS_SerialPrint_LFN) + if (lsParams.LFN) printf_P(PSTR("DIR_ENTER: %s \"%s\"\n"), path, longFilename[0] ? longFilename : lfilename); SdFile dir; if (!dir.open(parent, lfilename, O_READ)) { - if (lsAction == LS_SerialPrint || lsAction == LS_SerialPrint_LFN) { - //SERIAL_ECHO_START(); - //SERIAL_ECHOPGM(_i("Cannot open subdir"));////MSG_SD_CANT_OPEN_SUBDIR - //SERIAL_ECHOLN(lfilename); - } + //SERIAL_ECHO_START(); + //SERIAL_ECHOPGM(_i("Cannot open subdir"));////MSG_SD_CANT_OPEN_SUBDIR + //SERIAL_ECHOLN(lfilename); } - lsDive(path, dir); + lsDive(path, dir, NULL, lsAction, lsParams); // close() is done automatically by destructor of SdFile - if (lsAction == LS_SerialPrint_LFN) + if (lsParams.LFN) puts_P(PSTR("DIR_EXIT")); } else { - uint8_t pn0 = p.name[0]; - if (pn0 == DIR_NAME_FREE) break; - if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue; - if (longFilename[0] == '.') continue; - if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue; filenameIsDir = DIR_IS_SUBDIR(&p); if (!filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue; switch (lsAction) { @@ -129,17 +125,29 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m nrFiles++; break; - case LS_SerialPrint_LFN: case LS_SerialPrint: createFilename(filename, p); SERIAL_PROTOCOL(prepend); SERIAL_PROTOCOL(filename); + MYSERIAL.write(' '); + SERIAL_PROTOCOL(p.fileSize); - if (lsAction == LS_SerialPrint_LFN) - printf_P(PSTR("\"%s\" "), LONGEST_FILENAME); + if (lsParams.timestamp) + { + crmodDate = p.lastWriteDate; + crmodTime = p.lastWriteTime; + if( crmodDate < p.creationDate || ( crmodDate == p.creationDate && crmodTime < p.creationTime ) ){ + crmodDate = p.creationDate; + crmodTime = p.creationTime; + } + printf_P(PSTR(" %#lx"), ((uint32_t)crmodDate << 16) | crmodTime); + } - SERIAL_PROTOCOLLN(p.fileSize); + if (lsParams.LFN) + printf_P(PSTR(" \"%s\""), LONGEST_FILENAME); + + SERIAL_PROTOCOLLN(); manage_heater(); break; @@ -181,14 +189,10 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m } // while readDir } -void CardReader::ls(bool printLFN) +void CardReader::ls(ls_param params) { - lsAction = printLFN ? LS_SerialPrint_LFN : LS_SerialPrint; - //if(lsAction==LS_Count) - //nrFiles=0; - root.rewind(); - lsDive("",root); + lsDive("",root, NULL, LS_SerialPrint, params); } @@ -695,38 +699,34 @@ void CardReader::closefile(bool store_location) void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/) { curDir=&workDir; - lsAction=LS_GetFilename; nrFiles=nr; curDir->rewind(); - lsDive("",*curDir,match); + lsDive("",*curDir,match, LS_GetFilename); } void CardReader::getfilename_simple(uint32_t position, const char * const match/*=NULL*/) { curDir = &workDir; - lsAction = LS_GetFilename; nrFiles = 0; curDir->seekSet(position); - lsDive("", *curDir, match); + lsDive("", *curDir, match, LS_GetFilename); } void CardReader::getfilename_next(uint32_t position, const char * const match/*=NULL*/) { curDir = &workDir; - lsAction = LS_GetFilename; nrFiles = 1; curDir->seekSet(position); - lsDive("", *curDir, match); + lsDive("", *curDir, match, LS_GetFilename); } uint16_t CardReader::getnrfilenames() { curDir=&workDir; - lsAction=LS_Count; nrFiles=0; curDir->rewind(); - lsDive("",*curDir); + lsDive("",*curDir, NULL, LS_Count); //SERIAL_ECHOLN(nrFiles); return nrFiles; } diff --git a/Firmware/cardreader.h b/Firmware/cardreader.h index 715d82fa..c6e55428 100644 --- a/Firmware/cardreader.h +++ b/Firmware/cardreader.h @@ -8,12 +8,25 @@ #define MAX_DIR_DEPTH 6 #include "SdFile.h" -enum LsAction {LS_SerialPrint,LS_SerialPrint_LFN,LS_Count,LS_GetFilename}; class CardReader { public: CardReader(); + enum LsAction : uint8_t + { + LS_SerialPrint, + LS_Count, + LS_GetFilename, + }; + struct ls_param + { + bool LFN : 1; + bool timestamp : 1; + inline ls_param():LFN(0), timestamp(0) { } + inline ls_param(bool LFN, bool timestamp):LFN(LFN), timestamp(timestamp) { } + } __attribute__((packed)); + void initsd(); void write_command(char *buf); void write_command_no_newline(char *buf); @@ -43,7 +56,7 @@ public: uint16_t getWorkDirDepth(); - void ls(bool printLFN); + void ls(ls_param params); bool chdir(const char * relpath, bool doPresort); void updir(); void setroot(bool doPresort); @@ -59,9 +72,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;}; @@ -119,12 +135,11 @@ private: bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. - LsAction lsAction; //stored for recursion. int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. char* diveDirName; bool diveSubfolder (const char *&fileName); - void lsDive(const char *prepend, SdFile parent, const char * const match=NULL); + void lsDive(const char *prepend, SdFile parent, const char * const match=NULL, LsAction lsAction = LS_GetFilename, ls_param lsParams = ls_param()); #ifdef SDCARD_SORT_ALPHA void flush_presort(); #endif 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..ab904260 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 @@ -107,10 +110,10 @@ if (eeprom_read_byte((uint8_t*)EEPROM_PINDA_TEMP_COMPENSATION) == 0xff) eeprom_u //! | 1 | Smooth2 | //! | 2 | Textur1 | //! | 3 | Textur2 | -//! | 4 | Custom1 | -//! | 5 | Custom2 | -//! | 6 | Custom3 | -//! | 7 | Custom4 | +//! | 4 | Satin 1 | +//! | 5 | Satin 2 | +//! | 6 | Custom1 | +//! | 7 | Custom2 | //! //! @param[in] index //! @param[out] sheetName @@ -126,41 +129,16 @@ void eeprom_default_sheet_name(uint8_t index, SheetName &sheetName) { strcpy_P(sheetName.c, PSTR("Textur")); } + else if (index < 6) + { + strcpy_P(sheetName.c, PSTR("Satin ")); + } else { strcpy_P(sheetName.c, PSTR("Custom")); } - switch (index) - { - case 0: - sheetName.c[6] = '1'; - break; - case 1: - sheetName.c[6] = '2'; - break; - case 2: - sheetName.c[6] = '1'; - break; - case 3: - sheetName.c[6] = '2'; - break; - case 4: - sheetName.c[6] = '1'; - break; - case 5: - sheetName.c[6] = '2'; - break; - case 6: - sheetName.c[6] = '3'; - break; - case 7: - sheetName.c[6] = '4'; - break; - default: - break; - } - + sheetName.c[6] = '0' + ((index % 2)+1); sheetName.c[7] = '\0'; } diff --git a/Firmware/eeprom.h b/Firmware/eeprom.h index 2590d0f2..48cf6527 100644 --- a/Firmware/eeprom.h +++ b/Firmware/eeprom.h @@ -276,19 +276,19 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP | 0x0D71 3441 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 4th sheet - Z offset | ^ | D3 Ax0d71 C2 | 0x0D73 3443 | uint8 | ^ | 00h 0 | ffh 255 | 4th sheet - bed temp | ^ | D3 Ax0d73 C1 | 0x0D74 3444 | uint8 | ^ | 00h 0 | ffh 255 | 4th sheet - PINDA temp | ^ | D3 Ax0d74 C1 -| 0x0D75 3445 | char | _5th Sheet block_ | 437573746f6d31| ffffffffffffff | 5th sheet - Name: _Custom1_ | ^ | D3 Ax0d75 C7 +| 0x0D75 3445 | char | _5th Sheet block_ | 536174696e2031| ffffffffffffff | 5th sheet - Name: _Satin 1_ | ^ | D3 Ax0d75 C7 | 0x0D7C 3452 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 5th sheet - Z offset | ^ | D3 Ax0d7c C2 | 0x0D7E 3454 | uint8 | ^ | 00h 0 | ffh 255 | 5th sheet - bed temp | ^ | D3 Ax0d7e C1 | 0x0D7F 3455 | uint8 | ^ | 00h 0 | ffh 255 | 5th sheet - PINDA temp | ^ | D3 Ax0d7f C1 -| 0x0D80 3456 | char | _6th Sheet block_ | 437573746f6d32| ffffffffffffff | 6th sheet - Name: _Custom2_ | ^ | D3 Ax0d80 C7 +| 0x0D80 3456 | char | _6th Sheet block_ | 536174696e2032| ffffffffffffff | 6th sheet - Name: _Satin 2_ | ^ | D3 Ax0d80 C7 | 0x0D87 3463 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 6th sheet - Z offset | ^ | D3 Ax0d87 C2 | 0x0D89 3465 | uint8 | ^ | 00h 0 | ffh 255 | 6th sheet - bed temp | ^ | D3 Ax0d89 C1 | 0x0D8A 3466 | uint8 | ^ | 00h 0 | ffh 255 | 6th sheet - PINDA temp | ^ | D3 Ax0d8a C1 -| 0x0D8B 3467 | char | _7th Sheet block_ | 437573746f6d33| ffffffffffffff | 7th sheet - Name: _Custom3_ | ^ | D3 Ax0d8b C7 +| 0x0D8B 3467 | char | _7th Sheet block_ | 437573746f6d31| ffffffffffffff | 7th sheet - Name: _Custom1_ | ^ | D3 Ax0d8b C7 | 0x0D92 3474 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 7th sheet - Z offset | ^ | D3 Ax0d92 C2 | 0x0D94 3476 | uint8 | ^ | 00h 0 | ffh 255 | 7th sheet - bed temp | ^ | D3 Ax0d94 C1 | 0x0D95 3477 | uint8 | ^ | 00h 0 | ffh 255 | 7th sheet - PINDA temp | ^ | D3 Ax0d95 C1 -| 0x0D96 3478 | char | _8th Sheet block_ | 437573746f6d34| ffffffffffffff | 8th sheet - Name: _Custom4_ | ^ | D3 Ax0d96 C7 +| 0x0D96 3478 | char | _8th Sheet block_ | 437573746f6d32| ffffffffffffff | 8th sheet - Name: _Custom2_ | ^ | D3 Ax0d96 C7 | 0x0D9D 3485 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 8th sheet - Z offset | ^ | D3 Ax0d9d C2 | 0x0D9F 3487 | uint8 | ^ | 00h 0 | ffh 255 | 8th sheet - bed temp | ^ | D3 Ax0d9f C1 | 0x0DA0 3488 | uint8 | ^ | 00h 0 | ffh 255 | 8th sheet - PINDA temp | ^ | D3 Ax0da0 C1 @@ -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 cb921619..2b8bc248 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -2201,15 +2201,16 @@ void mFilamentItem(uint16_t nTemp, uint16_t nTempBed) } else { - lcd_set_cursor(0, 0); - lcdui_print_temp(LCD_STR_THERMOMETER[0], (int) degHotend(0), (int) degTargetHotend(0)); - if (!bFilamentWaitingFlag) { // First run after the filament preheat selection: // setup the fixed LCD parts and raise Z as we wait bFilamentWaitingFlag = true; + lcd_clear(); + lcd_draw_update = 1; + lcd_puts_at_P(0, 3, _i(">Cancel")); ////MSG_ c=20 r=1 + lcd_set_cursor(0, 1); switch (eFilamentAction) { @@ -2236,9 +2237,15 @@ void mFilamentItem(uint16_t nTemp, uint16_t nTempBed) // handled earlier break; } +<<<<<<< HEAD lcd_puts_at_P(0, 3, _T(MSG_CANCEL)); +======= +>>>>>>> upstream/MK3_3.10.0 } + lcd_set_cursor(0, 0); + lcdui_print_temp(LCD_STR_THERMOMETER[0], (int) degHotend(0), (int) degTargetHotend(0)); + if (lcd_clicked()) { bFilamentWaitingFlag = false; @@ -4361,7 +4368,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 +4382,7 @@ static void lcd_community_language_menu() } MENU_END(); } -#endif //W25X20CL +#endif //XFLASH #endif //COMMUNITY_LANG_SUPPORT && W52X20CL @@ -4390,7 +4397,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 +4408,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 +4418,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(); @@ -4885,7 +4892,7 @@ void lcd_wizard(WizState state) lcd_display_message_fullscreen_P(_i("Now I will preheat nozzle for PLA.")); wait_preheat(); //unload current filament - unload_filament(); + unload_filament(true); //load filament lcd_wizard_load(); setTargetHotend(0, 0); //we are finished, cooldown nozzle @@ -6200,13 +6207,14 @@ static void change_extr_menu(){ } #endif //SNMM -//unload filament for single material printer (used in M702 gcode) -void unload_filament() +// unload filament for single material printer (used in M702 gcode) +// @param automatic: If true, unload_filament is part of a unload+load sequence (M600) +void unload_filament(bool automatic) { custom_message_type = CustomMsg::FilamentLoading; lcd_setstatuspgm(_T(MSG_UNLOADING_FILAMENT)); - raise_z_above(MIN_Z_FOR_UNLOAD); + raise_z_above(automatic? MIN_Z_FOR_SWAP: MIN_Z_FOR_UNLOAD); // extr_unload2(); @@ -6323,15 +6331,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 +6680,11 @@ static void lcd_main_menu() } MENU_ITEM_SUBMENU_P(_i("Support"), lcd_support_menu);////MSG_SUPPORT c=18 #ifdef LCD_TEST +<<<<<<< HEAD MENU_ITEM_SUBMENU_P(_i("W25x20CL init"), lcd_test_menu); +======= + MENU_ITEM_SUBMENU_P(_i("XFLASH init"), lcd_test_menu);////MSG_SUPPORT +>>>>>>> upstream/MK3_3.10.0 #endif //LCD_TEST MENU_END(); diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index 008a106e..c671326e 100755 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -195,7 +195,7 @@ extern bool bFilamentAction; void mFilamentItem(uint16_t nTemp,uint16_t nTempBed); void mFilamentItemForce(); void lcd_generic_preheat_menu(); -void unload_filament(); +void unload_filament(bool automatic = false); void stack_error(); void lcd_printer_connected(); 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(); diff --git a/lang/lang-build.sh b/lang/lang-build.sh index ed681c9e..eab09cfc 100755 --- a/lang/lang-build.sh +++ b/lang/lang-build.sh @@ -88,7 +88,7 @@ generate_binary() rm -f lang_$1.dat LNG=$1 #check lang dictionary - ./lang-check.py $1 --no-warning + ./lang-check.py $1 #--no-warning #create lang_xx.tmp - different processing for 'en' language if [ "$1" = "en" ]; then #remove comments and empty lines diff --git a/lang/lang-check.py b/lang/lang-check.py index 86e543ab..9446d827 100755 --- a/lang/lang-check.py +++ b/lang/lang-check.py @@ -1,9 +1,25 @@ #!/usr/bin/env python3 +# +# Version 1.0.1 +# +############################################################################# +# Change log: +# 7 May 2019, Ondrej Tuma, Initial +# 9 June 2020, 3d-gussner, Added version and Change log +# 9 June 2020, 3d-gussner, Wrap text to 20 char and rows +# 9 June 2020, 3d-gussner, colored output +# 2 Apr. 2021, 3d-gussner, Fix and improve text warp +############################################################################# +# """Check lang files.""" from argparse import ArgumentParser from traceback import print_exc from sys import stderr +import textwrap +red = lambda text: '\033[0;31m' + text + '\033[0m' +green = lambda text: '\033[0;32m' + text + '\033[0m' +yellow = lambda text: '\033[0;33m' + text + '\033[0m' def parse_txt(lang, no_warning): """Parse txt file and check strings to display definition.""" @@ -12,48 +28,67 @@ def parse_txt(lang, no_warning): else: file_path = "lang_en_%s.txt" % lang + print(green("Start %s lang-check" % lang)) + lines = 1 with open(file_path) as src: while True: comment = src.readline().split(' ') - src.readline() # source + #print (comment) #Debug + source = src.readline()[:-1] + #print (source) #Debug translation = src.readline()[:-1] + #print (translation) #Debug +#Wrap text to 20 chars and rows + wrapper = textwrap.TextWrapper(width=20) + #wrap original/source + rows_count_source = 0 + for line in wrapper.wrap(source.strip('"')): + rows_count_source += 1 + #print (line) #Debug + #wrap translation + rows_count_translation = 0 + for line in wrapper.wrap(translation.strip('"')): + rows_count_translation += 1 + #print (line) #Debug +#End wrap text +#Check if columns and rows are defined cols = None rows = None for item in comment[1:]: key, val = item.split('=') if key == 'c': cols = int(val) + #print ("c=",cols) #Debug elif key == 'r': rows = int(val) + #print ("r=",rows) #Debug else: raise RuntimeError( "Unknown display definition %s on line %d" % (' '.join(comment), lines)) if cols is None and rows is None: if not no_warning: - print("[W]: No display definition on line %d" % lines) + print(yellow("[W]: No display definition on line %d" % lines)) cols = len(translation) # propably fullscreen if rows is None: rows = 1 - if len(translation)-2 > cols*rows: - stderr.write( - "[E]: Text %s is longer then definiton on line %d\n" % - (translation, lines)) - stderr.flush() + if rows_count_translation > rows_count_source and rows_count_translation > rows: + print(red("[E]: Text %s is longer then definiton on line %d rows diff=%d, EN=%s\n" % (translation, lines, rows_count_translation-rows, source))) if len(src.readline()) != 1: # empty line break lines += 4 + print(green("End %s lang-check" % lang)) def main(): """Main function.""" parser = ArgumentParser( description=__doc__, - usage="$(prog)s lang") + usage="%(prog)s lang") parser.add_argument( "lang", nargs='?', default="en", type=str, help="Check lang file (en|cs|de|es|fr|nl|it|pl)")