/* settings.c - eeprom configuration handling Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud Copyright (c) 2011-2012 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Grbl is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Grbl. If not, see . */ #include #include #include "nuts_bolts.h" #include "settings.h" #include "eeprom.h" #include "print.h" #include #include "protocol.h" #include "config.h" settings_t settings; // Version 1 outdated settings record typedef struct { float steps_per_mm[3]; uint8_t microsteps; uint8_t pulse_microseconds; float default_feed_rate; float default_seek_rate; uint8_t invert_mask; float mm_per_arc_segment; } settings_v1_t; // Version 2,3,4 outdated settings record typedef struct { float steps_per_mm[3]; uint8_t microsteps; uint8_t pulse_microseconds; float default_feed_rate; float default_seek_rate; uint8_t invert_mask; float mm_per_arc_segment; float acceleration; float junction_deviation; } settings_v2_v4_t; // Default settings (used when resetting eeprom-settings) #define MICROSTEPS 8 #define DEFAULT_X_STEPS_PER_MM (94.488188976378*MICROSTEPS) #define DEFAULT_Y_STEPS_PER_MM (94.488188976378*MICROSTEPS) #define DEFAULT_Z_STEPS_PER_MM (94.488188976378*MICROSTEPS) #define DEFAULT_STEP_PULSE_MICROSECONDS 30 #define DEFAULT_MM_PER_ARC_SEGMENT 0.1 #define DEFAULT_RAPID_FEEDRATE 500.0 // mm/min #define DEFAULT_FEEDRATE 500.0 #define DEFAULT_ACCELERATION (DEFAULT_FEEDRATE*60*60/10.0) // mm/min^2 #define DEFAULT_JUNCTION_DEVIATION 0.05 // mm #define DEFAULT_STEPPING_INVERT_MASK ((1<= 'A' || line[char_counter] <= 'Z') { // letter = line[char_counter++]; // if(line[char_counter++] != '=') { // return(STATUS_UNSUPPORTED_STATEMENT); // } // for (char_counter = 0; char_counter < LINE_BUFFER_SIZE-3; char_counter++) { // line[char_counter] = line[char_counter+3]; // } // uint8_t status = gc_execute_line(line); // if (status) { return(status); } // else { settings_store_startup_line(line); } // // // // Opt stop and block delete are referred to as switches. // // How to store home position and work offsets real-time?? // // } else { if(!read_float(line, &char_counter, ¶meter)) { return(STATUS_SETTING_INVALID); } if(line[char_counter++] != '=') { return(STATUS_SETTING_INVALID); } if(!read_float(line, &char_counter, &value)) { return(STATUS_SETTING_INVALID); } if(line[char_counter] != 0) { return(STATUS_SETTING_INVALID); } return(settings_store_setting(parameter, value)); // } } void write_settings() { eeprom_put_char(0, SETTINGS_VERSION); memcpy_to_eeprom_with_checksum(1, (char*)&settings, sizeof(settings_t)); // // char buf[4]; buf[0] = 'G'; buf[1] = '2'; buf[2] = '0'; buf[3] = 0; // memcpy_to_eeprom_with_checksum(512, (char*)buf, 4); // } int read_settings() { // Check version-byte of eeprom uint8_t version = eeprom_get_char(0); if (version == SETTINGS_VERSION) { // Read settings-record and check checksum if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_t)))) { return(false); } } else { // Incrementally update the old versions until up-to-date. if (version == 1) { // Migrate from settings version 1 to version 4. if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v1_t)))) { return(false); } settings.acceleration = DEFAULT_ACCELERATION; settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION; } else if ((version == 2) || (version == 3)) { // Migrate from settings version 2 and 3 to version 4. if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v2_v4_t)))) { return(false); } if (version == 2) { settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION; } settings.acceleration *= 3600; // Convert to mm/min^2 from mm/sec^2 } if (version <= 4) { // Migrate from settings version 4 to current version. if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v2_v4_t)))) { return(false); } settings_reset(false); write_settings(); } else if (version >= 50) { // Developmental settings. Version numbers greater than or equal to 50 are temporary. // Currently, this will update the user settings to v4 and the remainder of the settings // should be re-written to the default value, if the developmental version number changed. // Grab settings regardless of error. memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_t)); settings_reset(false); write_settings(); } else { return(false); } } return(true); } // A helper method to set settings from command line int8_t settings_store_setting(int parameter, float value) { switch(parameter) { case 0: case 1: case 2: if (value <= 0.0) { return(STATUS_SETTING_STEPS_NEG); } settings.steps_per_mm[parameter] = value; break; case 3: if (value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); } settings.pulse_microseconds = round(value); break; case 4: settings.default_feed_rate = value; break; case 5: settings.default_seek_rate = value; break; case 6: settings.mm_per_arc_segment = value; break; case 7: settings.invert_mask = trunc(value); break; case 8: settings.acceleration = value*60*60; break; // Convert to mm/min^2 for grbl internal use. case 9: settings.junction_deviation = fabs(value); break; case 10: if (value) { settings.flags |= BITFLAG_REPORT_INCHES; } else { settings.flags &= ~BITFLAG_REPORT_INCHES; } break; case 11: if (value) { settings.flags |= BITFLAG_AUTO_START; } else { settings.flags &= ~BITFLAG_AUTO_START; } break; case 12: if (value) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; } else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; } break; case 13: if (value) { settings.flags |= BITFLAG_HOMING_ENABLE; protocol_warning_message(WARNING_HOMING_ENABLE); } else { settings.flags &= ~BITFLAG_HOMING_ENABLE; } break; case 14: settings.homing_dir_mask = trunc(value); break; case 15: settings.homing_feed_rate = value; break; case 16: settings.homing_seek_rate = value; break; case 17: settings.homing_debounce_delay = round(value); break; case 18: settings.homing_pulloff = value; break; case 19: settings.stepper_idle_lock_time = round(value); // TODO: Immediately check and toggle steppers from always enable or disable? break; case 20: settings.decimal_places = round(value); break; default: return(STATUS_SETTING_INVALID); } write_settings(); return(STATUS_OK); } // Initialize the config subsystem void settings_init() { if(!read_settings()) { protocol_warning_message(WARNING_SETTING_READ_FAIL); settings_reset(true); write_settings(); settings_dump(); } } // int8_t settings_execute_startup() { // // char buf[4]; // settings_startup_string((char *)buf); // uint8_t i = 0; // while (i < 4) { // serial_write(buf[i++]); // } // return(gc_execute_line(buf)); // }