Sergey Pastor / grbl
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers settings.c Source File

settings.c

00001 /*
00002   settings.c - eeprom configuration handling
00003   Part of Grbl
00004 
00005   Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
00006   Copyright (c) 2009-2011 Simen Svale Skogsrud
00007 
00008   Grbl is free software: you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation, either version 3 of the License, or
00011   (at your option) any later version.
00012 
00013   Grbl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017 
00018   You should have received a copy of the GNU General Public License
00019   along with Grbl.  If not, see <http://www.gnu.org/licenses/>.
00020 */
00021 
00022 #include "grbl.h"
00023 
00024 settings_t settings;
00025 
00026 
00027 // Method to store startup lines into EEPROM
00028 void settings_store_startup_line(uint8_t n, char *line)
00029 {
00030   #ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE
00031     protocol_buffer_synchronize(); // A startup line may contain a motion and be executing. 
00032   #endif
00033   uint32_t addr = n*(LINE_BUFFER_SIZE+1)+EEPROM_ADDR_STARTUP_BLOCK;
00034   memcpy_to_eeprom_with_checksum(addr,(char*)line, LINE_BUFFER_SIZE);
00035 }
00036 
00037 
00038 // Method to store build info into EEPROM
00039 // NOTE: This function can only be called in IDLE state.
00040 void settings_store_build_info(char *line)
00041 {
00042   // Build info can only be stored when state is IDLE.
00043   memcpy_to_eeprom_with_checksum(EEPROM_ADDR_BUILD_INFO,(char*)line, LINE_BUFFER_SIZE);
00044 }
00045 
00046 
00047 // Method to store coord data parameters into EEPROM
00048 void settings_write_coord_data(uint8_t coord_select, float *coord_data)
00049 {
00050   #ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE
00051     protocol_buffer_synchronize();
00052   #endif
00053   uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS;
00054   memcpy_to_eeprom_with_checksum(addr,(char*)coord_data, sizeof(float)*N_AXIS);
00055 }
00056 
00057 
00058 // Method to store Grbl global settings struct and version number into EEPROM
00059 // NOTE: This function can only be called in IDLE state.
00060 void write_global_settings()
00061 {
00062   eeprom_put_char(0, SETTINGS_VERSION);
00063   memcpy_to_eeprom_with_checksum(EEPROM_ADDR_GLOBAL, (char*)&settings, sizeof(settings_t));
00064 }
00065 
00066 
00067 // Method to restore EEPROM-saved Grbl global settings back to defaults.
00068 void settings_restore(uint8_t restore_flag) {
00069   if (restore_flag & SETTINGS_RESTORE_DEFAULTS) {
00070     settings.pulse_microseconds = DEFAULT_STEP_PULSE_MICROSECONDS;
00071     settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME;
00072     settings.step_invert_mask = DEFAULT_STEPPING_INVERT_MASK;
00073     settings.dir_invert_mask = DEFAULT_DIRECTION_INVERT_MASK;
00074     settings.status_report_mask = DEFAULT_STATUS_REPORT_MASK;
00075     settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION;
00076     settings.arc_tolerance = DEFAULT_ARC_TOLERANCE;
00077 
00078     settings.rpm_max = DEFAULT_SPINDLE_RPM_MAX;
00079     settings.rpm_min = DEFAULT_SPINDLE_RPM_MIN;
00080 
00081     settings.homing_dir_mask = DEFAULT_HOMING_DIR_MASK;
00082     settings.homing_feed_rate = DEFAULT_HOMING_FEED_RATE;
00083     settings.homing_seek_rate = DEFAULT_HOMING_SEEK_RATE;
00084     settings.homing_debounce_delay = DEFAULT_HOMING_DEBOUNCE_DELAY;
00085     settings.homing_pulloff = DEFAULT_HOMING_PULLOFF;
00086 
00087     settings.flags = 0;
00088     if (DEFAULT_REPORT_INCHES) { settings.flags |= BITFLAG_REPORT_INCHES; }
00089     if (DEFAULT_LASER_MODE) { settings.flags |= BITFLAG_LASER_MODE; }
00090     if (DEFAULT_INVERT_ST_ENABLE) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; }
00091     if (DEFAULT_HARD_LIMIT_ENABLE) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; }
00092     if (DEFAULT_HOMING_ENABLE) { settings.flags |= BITFLAG_HOMING_ENABLE; }
00093     if (DEFAULT_SOFT_LIMIT_ENABLE) { settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; }
00094     if (DEFAULT_INVERT_LIMIT_PINS) { settings.flags |= BITFLAG_INVERT_LIMIT_PINS; }
00095     if (DEFAULT_INVERT_PROBE_PIN) { settings.flags |= BITFLAG_INVERT_PROBE_PIN; }
00096 
00097     settings.steps_per_mm[X_AXIS] = DEFAULT_X_STEPS_PER_MM;
00098     settings.steps_per_mm[Y_AXIS] = DEFAULT_Y_STEPS_PER_MM;
00099     settings.steps_per_mm[Z_AXIS] = DEFAULT_Z_STEPS_PER_MM;
00100     settings.max_rate[X_AXIS] = DEFAULT_X_MAX_RATE;
00101     settings.max_rate[Y_AXIS] = DEFAULT_Y_MAX_RATE;
00102     settings.max_rate[Z_AXIS] = DEFAULT_Z_MAX_RATE;
00103     settings.acceleration[X_AXIS] = DEFAULT_X_ACCELERATION;
00104     settings.acceleration[Y_AXIS] = DEFAULT_Y_ACCELERATION;
00105     settings.acceleration[Z_AXIS] = DEFAULT_Z_ACCELERATION;
00106     settings.max_travel[X_AXIS] = (-DEFAULT_X_MAX_TRAVEL);
00107     settings.max_travel[Y_AXIS] = (-DEFAULT_Y_MAX_TRAVEL);
00108     settings.max_travel[Z_AXIS] = (-DEFAULT_Z_MAX_TRAVEL);
00109 
00110     write_global_settings();
00111   }
00112 
00113   if (restore_flag & SETTINGS_RESTORE_PARAMETERS) {
00114     uint8_t idx;
00115     float coord_data[N_AXIS];
00116     memset(&coord_data, 0, sizeof(coord_data));
00117     for (idx=0; idx <= SETTING_INDEX_NCOORD; idx++) { settings_write_coord_data(idx, coord_data); }
00118   }
00119 
00120   if (restore_flag & SETTINGS_RESTORE_STARTUP_LINES) {
00121     #if N_STARTUP_LINE > 0
00122       eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK, 0);
00123       eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+1, 0); // Checksum
00124     #endif
00125     #if N_STARTUP_LINE > 1
00126       eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+(LINE_BUFFER_SIZE+1), 0);
00127       eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+(LINE_BUFFER_SIZE+2), 0); // Checksum
00128     #endif
00129   }
00130 
00131   if (restore_flag & SETTINGS_RESTORE_BUILD_INFO) {
00132     eeprom_put_char(EEPROM_ADDR_BUILD_INFO , 0);
00133     eeprom_put_char(EEPROM_ADDR_BUILD_INFO+1 , 0); // Checksum
00134   }
00135 }
00136 
00137 
00138 // Reads startup line from EEPROM. Updated pointed line string data.
00139 uint8_t settings_read_startup_line(uint8_t n, char *line)
00140 {
00141   uint32_t addr = n*(LINE_BUFFER_SIZE+1)+EEPROM_ADDR_STARTUP_BLOCK;
00142   if (!(memcpy_from_eeprom_with_checksum((char*)line, addr, LINE_BUFFER_SIZE))) {
00143     // Reset line with default value
00144     line[0] = 0; // Empty line
00145     settings_store_startup_line(n, line);
00146     return(false);
00147   }
00148   return(true);
00149 }
00150 
00151 
00152 // Reads startup line from EEPROM. Updated pointed line string data.
00153 uint8_t settings_read_build_info(char *line)
00154 {
00155   if (!(memcpy_from_eeprom_with_checksum((char*)line, EEPROM_ADDR_BUILD_INFO, LINE_BUFFER_SIZE))) {
00156     // Reset line with default value
00157     line[0] = 0; // Empty line
00158     settings_store_build_info(line);
00159     return(false);
00160   }
00161   return(true);
00162 }
00163 
00164 
00165 // Read selected coordinate data from EEPROM. Updates pointed coord_data value.
00166 uint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data)
00167 {
00168   uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS;
00169   if (!(memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float)*N_AXIS))) {
00170     // Reset with default zero vector
00171     clear_vector_float(coord_data);
00172     settings_write_coord_data(coord_select,coord_data);
00173     return(false);
00174   }
00175   return(true);
00176 }
00177 
00178 
00179 // Reads Grbl global settings struct from EEPROM.
00180 uint8_t read_global_settings() {
00181   // Check version-byte of eeprom
00182   uint8_t version = eeprom_get_char(0);
00183   if (version == SETTINGS_VERSION) {
00184     // Read settings-record and check checksum
00185     if (!(memcpy_from_eeprom_with_checksum((char*)&settings, EEPROM_ADDR_GLOBAL, sizeof(settings_t)))) {
00186       return(false);
00187     }
00188   } else {
00189     return(false);
00190   }
00191   return(true);
00192 }
00193 
00194 
00195 // A helper method to set settings from command line
00196 uint8_t settings_store_global_setting(uint8_t parameter, float value) {
00197   if (value < 0.0f) { return(STATUS_NEGATIVE_VALUE); }
00198   if (parameter >= AXIS_SETTINGS_START_VAL) {
00199     // Store axis configuration. Axis numbering sequence set by AXIS_SETTING defines.
00200     // NOTE: Ensure the setting index corresponds to the report.c settings printout.
00201     parameter -= AXIS_SETTINGS_START_VAL;
00202     uint8_t set_idx = 0;
00203     while (set_idx < AXIS_N_SETTINGS) {
00204       if (parameter < N_AXIS) {
00205         // Valid axis setting found.
00206         switch (set_idx) {
00207           case 0:
00208             #ifdef MAX_STEP_RATE_HZ
00209             if (value*settings.max_rate[parameter] >(MAX_STEP_RATE_HZ*60.0f)) { return(STATUS_MAX_STEP_RATE_EXCEEDED); }
00210             #endif
00211             settings.steps_per_mm[parameter] = value;
00212             break;
00213           case 1:
00214             #ifdef MAX_STEP_RATE_HZ
00215             if (value*settings.steps_per_mm[parameter] > (MAX_STEP_RATE_HZ*60.0f)) { return(STATUS_MAX_STEP_RATE_EXCEEDED); }
00216             #endif
00217             settings.max_rate[parameter] = value;
00218             break;
00219           case 2: settings.acceleration[parameter] = value*60*60; break; // Convert to mm/min^2 for grbl internal use.
00220           case 3: settings.max_travel[parameter] = -value; break;  // Store as negative for grbl internal use.
00221         }
00222         break; // Exit while-loop after setting has been configured and proceed to the EEPROM write call.
00223       } else {
00224         set_idx++;
00225         // If axis index greater than N_AXIS or setting index greater than number of axis settings, error out.
00226         if ((parameter < AXIS_SETTINGS_INCREMENT) || (set_idx == AXIS_N_SETTINGS)) { return(STATUS_INVALID_STATEMENT); }
00227         parameter -= AXIS_SETTINGS_INCREMENT;
00228       }
00229     }
00230   } else {
00231     // Store non-axis Grbl settings
00232     uint8_t int_value = truncf(value);
00233     switch(parameter) {
00234       case 0:
00235         if (int_value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); }
00236         settings.pulse_microseconds = int_value; break;
00237       case 1: settings.stepper_idle_lock_time = int_value; break;
00238       case 2:
00239         settings.step_invert_mask = int_value;
00240         st_generate_step_dir_invert_masks(); // Regenerate step and direction port invert masks.
00241         break;
00242       case 3:
00243         settings.dir_invert_mask = int_value;
00244         st_generate_step_dir_invert_masks(); // Regenerate step and direction port invert masks.
00245         break;
00246       case 4: // Reset to ensure change. Immediate re-init may cause problems.
00247         if (int_value) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; }
00248         else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; }
00249         break;
00250       case 5: // Reset to ensure change. Immediate re-init may cause problems.
00251         if (int_value) { settings.flags |= BITFLAG_INVERT_LIMIT_PINS; }
00252         else { settings.flags &= ~BITFLAG_INVERT_LIMIT_PINS; }
00253         break;
00254       case 6: // Reset to ensure change. Immediate re-init may cause problems.
00255         if (int_value) { settings.flags |= BITFLAG_INVERT_PROBE_PIN; }
00256         else { settings.flags &= ~BITFLAG_INVERT_PROBE_PIN; }
00257         probe_configure_invert_mask(false);
00258         break;
00259       case 10: settings.status_report_mask = int_value; break;
00260       case 11: settings.junction_deviation = value; break;
00261       case 12: settings.arc_tolerance = value; break;
00262       case 13:
00263         if (int_value) { settings.flags |= BITFLAG_REPORT_INCHES; }
00264         else { settings.flags &= ~BITFLAG_REPORT_INCHES; }
00265         system_flag_wco_change(); // Make sure WCO is immediately updated.
00266         break;
00267       case 20:
00268         if (int_value) {
00269           if (bit_isfalse(settings.flags, BITFLAG_HOMING_ENABLE)) { return(STATUS_SOFT_LIMIT_ERROR); }
00270           settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE;
00271         } else { settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; }
00272         break;
00273       case 21:
00274         if (int_value) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; }
00275         else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; }
00276         limits_init(); // Re-init to immediately change. NOTE: Nice to have but could be problematic later.
00277         break;
00278       case 22:
00279         if (int_value) { settings.flags |= BITFLAG_HOMING_ENABLE; }
00280         else {
00281           settings.flags &= ~BITFLAG_HOMING_ENABLE;
00282           settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; // Force disable soft-limits.
00283         }
00284         break;
00285       case 23: settings.homing_dir_mask = int_value; break;
00286       case 24: settings.homing_feed_rate = value; break;
00287       case 25: settings.homing_seek_rate = value; break;
00288       case 26: settings.homing_debounce_delay = int_value; break;
00289       case 27: settings.homing_pulloff = value; break;
00290       case 30: settings.rpm_max = value; spindle_init(); break; // Re-initialize spindle rpm calibration
00291       case 31: settings.rpm_min = value; spindle_init(); break; // Re-initialize spindle rpm calibration
00292       case 32:
00293         #ifdef VARIABLE_SPINDLE
00294           if (int_value) { settings.flags |= BITFLAG_LASER_MODE; }
00295           else { settings.flags &= ~BITFLAG_LASER_MODE; }
00296         #else
00297                 return(STATUS_SETTING_DISABLED_LASER);
00298         #endif
00299         break;
00300       default:
00301         return(STATUS_INVALID_STATEMENT);
00302     }
00303   }
00304   write_global_settings();
00305   return(STATUS_OK);
00306 }
00307 
00308 
00309 // Initialize the config subsystem
00310 void settings_init() {
00311   if(!read_global_settings()) {
00312     report_status_message(STATUS_SETTING_READ_FAIL);
00313     settings_restore(SETTINGS_RESTORE_ALL); // Force restore all EEPROM data.
00314     report_grbl_settings();
00315   }
00316 }
00317