blob: e607506b41e61867ecc24ee2386d95b630705565 [file] [log] [blame]
Luigi Santivetti69972f92019-11-12 22:55:40 +00001/*
2 settings.c - eeprom configuration handling
3 Part of Grbl
4
5 Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
6 Copyright (c) 2009-2011 Simen Svale Skogsrud
7
8 Grbl is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Grbl is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Grbl. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "grbl.h"
23
24settings_t settings;
25
26const __flash settings_t defaults = {\
27 .pulse_microseconds = DEFAULT_STEP_PULSE_MICROSECONDS,
28 .stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME,
29 .step_invert_mask = DEFAULT_STEPPING_INVERT_MASK,
30 .dir_invert_mask = DEFAULT_DIRECTION_INVERT_MASK,
31 .status_report_mask = DEFAULT_STATUS_REPORT_MASK,
32 .junction_deviation = DEFAULT_JUNCTION_DEVIATION,
33 .arc_tolerance = DEFAULT_ARC_TOLERANCE,
34 .rpm_max = DEFAULT_SPINDLE_RPM_MAX,
35 .rpm_min = DEFAULT_SPINDLE_RPM_MIN,
36 .homing_dir_mask = DEFAULT_HOMING_DIR_MASK,
37 .homing_feed_rate = DEFAULT_HOMING_FEED_RATE,
38 .homing_seek_rate = DEFAULT_HOMING_SEEK_RATE,
39 .homing_debounce_delay = DEFAULT_HOMING_DEBOUNCE_DELAY,
40 .homing_pulloff = DEFAULT_HOMING_PULLOFF,
41 .flags = (DEFAULT_REPORT_INCHES << BIT_REPORT_INCHES) | \
42 (DEFAULT_LASER_MODE << BIT_LASER_MODE) | \
43 (DEFAULT_INVERT_ST_ENABLE << BIT_INVERT_ST_ENABLE) | \
44 (DEFAULT_HARD_LIMIT_ENABLE << BIT_HARD_LIMIT_ENABLE) | \
45 (DEFAULT_HOMING_ENABLE << BIT_HOMING_ENABLE) | \
46 (DEFAULT_SOFT_LIMIT_ENABLE << BIT_SOFT_LIMIT_ENABLE) | \
47 (DEFAULT_INVERT_LIMIT_PINS << BIT_INVERT_LIMIT_PINS) | \
Luigi Santivetti42a1b332019-11-17 22:31:46 +000048 (DEFAULT_INVERT_PROBE_PIN << BIT_INVERT_PROBE_PIN)
49 #ifdef USE_ADC
50 | (DEFAULT_ENABLE_ADC << BIT_ADC_ENABLE)
51 #endif
52 ,
Luigi Santivetti69972f92019-11-12 22:55:40 +000053 .steps_per_mm[X_AXIS] = DEFAULT_X_STEPS_PER_MM,
54 .steps_per_mm[Y_AXIS] = DEFAULT_Y_STEPS_PER_MM,
55 .steps_per_mm[Z_AXIS] = DEFAULT_Z_STEPS_PER_MM,
56 .max_rate[X_AXIS] = DEFAULT_X_MAX_RATE,
57 .max_rate[Y_AXIS] = DEFAULT_Y_MAX_RATE,
58 .max_rate[Z_AXIS] = DEFAULT_Z_MAX_RATE,
59 .acceleration[X_AXIS] = DEFAULT_X_ACCELERATION,
60 .acceleration[Y_AXIS] = DEFAULT_Y_ACCELERATION,
61 .acceleration[Z_AXIS] = DEFAULT_Z_ACCELERATION,
62 .max_travel[X_AXIS] = (-DEFAULT_X_MAX_TRAVEL),
63 .max_travel[Y_AXIS] = (-DEFAULT_Y_MAX_TRAVEL),
64 .max_travel[Z_AXIS] = (-DEFAULT_Z_MAX_TRAVEL)};
65
66
67// Method to store startup lines into EEPROM
68void settings_store_startup_line(uint8_t n, char *line)
69{
70 #ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE
71 protocol_buffer_synchronize(); // A startup line may contain a motion and be executing.
72 #endif
73 uint32_t addr = n*(LINE_BUFFER_SIZE+1)+EEPROM_ADDR_STARTUP_BLOCK;
74 memcpy_to_eeprom_with_checksum(addr,(char*)line, LINE_BUFFER_SIZE);
75}
76
77
78// Method to store build info into EEPROM
79// NOTE: This function can only be called in IDLE state.
80void settings_store_build_info(char *line)
81{
82 // Build info can only be stored when state is IDLE.
83 memcpy_to_eeprom_with_checksum(EEPROM_ADDR_BUILD_INFO,(char*)line, LINE_BUFFER_SIZE);
84}
85
86
87// Method to store coord data parameters into EEPROM
88void settings_write_coord_data(uint8_t coord_select, float *coord_data)
89{
90 #ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE
91 protocol_buffer_synchronize();
92 #endif
93 uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS;
94 memcpy_to_eeprom_with_checksum(addr,(char*)coord_data, sizeof(float)*N_AXIS);
95}
96
97
98// Method to store Grbl global settings struct and version number into EEPROM
99// NOTE: This function can only be called in IDLE state.
100void write_global_settings()
101{
102 eeprom_put_char(0, SETTINGS_VERSION);
103 memcpy_to_eeprom_with_checksum(EEPROM_ADDR_GLOBAL, (char*)&settings, sizeof(settings_t));
104}
105
106
107// Method to restore EEPROM-saved Grbl global settings back to defaults.
108void settings_restore(uint8_t restore_flag) {
109 if (restore_flag & SETTINGS_RESTORE_DEFAULTS) {
110 settings = defaults;
111 write_global_settings();
112 }
113
114 if (restore_flag & SETTINGS_RESTORE_PARAMETERS) {
115 uint8_t idx;
116 float coord_data[N_AXIS];
117 memset(&coord_data, 0, sizeof(coord_data));
118 for (idx=0; idx <= SETTING_INDEX_NCOORD; idx++) { settings_write_coord_data(idx, coord_data); }
119 }
120
121 if (restore_flag & SETTINGS_RESTORE_STARTUP_LINES) {
122 #if N_STARTUP_LINE > 0
123 eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK, 0);
124 eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+1, 0); // Checksum
125 #endif
126 #if N_STARTUP_LINE > 1
127 eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+(LINE_BUFFER_SIZE+1), 0);
128 eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+(LINE_BUFFER_SIZE+2), 0); // Checksum
129 #endif
130 }
131
132 if (restore_flag & SETTINGS_RESTORE_BUILD_INFO) {
133 eeprom_put_char(EEPROM_ADDR_BUILD_INFO , 0);
134 eeprom_put_char(EEPROM_ADDR_BUILD_INFO+1 , 0); // Checksum
135 }
136}
137
138
139// Reads startup line from EEPROM. Updated pointed line string data.
140uint8_t settings_read_startup_line(uint8_t n, char *line)
141{
142 uint32_t addr = n*(LINE_BUFFER_SIZE+1)+EEPROM_ADDR_STARTUP_BLOCK;
143 if (!(memcpy_from_eeprom_with_checksum((char*)line, addr, LINE_BUFFER_SIZE))) {
144 // Reset line with default value
145 line[0] = 0; // Empty line
146 settings_store_startup_line(n, line);
147 return(false);
148 }
149 return(true);
150}
151
152
153// Reads startup line from EEPROM. Updated pointed line string data.
154uint8_t settings_read_build_info(char *line)
155{
156 if (!(memcpy_from_eeprom_with_checksum((char*)line, EEPROM_ADDR_BUILD_INFO, LINE_BUFFER_SIZE))) {
157 // Reset line with default value
158 line[0] = 0; // Empty line
159 settings_store_build_info(line);
160 return(false);
161 }
162 return(true);
163}
164
165
166// Read selected coordinate data from EEPROM. Updates pointed coord_data value.
167uint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data)
168{
169 uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS;
170 if (!(memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float)*N_AXIS))) {
171 // Reset with default zero vector
172 clear_vector_float(coord_data);
173 settings_write_coord_data(coord_select,coord_data);
174 return(false);
175 }
176 return(true);
177}
178
179
180// Reads Grbl global settings struct from EEPROM.
181uint8_t read_global_settings() {
182 // Check version-byte of eeprom
183 uint8_t version = eeprom_get_char(0);
184 if (version == SETTINGS_VERSION) {
185 // Read settings-record and check checksum
186 if (!(memcpy_from_eeprom_with_checksum((char*)&settings, EEPROM_ADDR_GLOBAL, sizeof(settings_t)))) {
187 return(false);
188 }
189 } else {
190 return(false);
191 }
192 return(true);
193}
194
195
196// A helper method to set settings from command line
197uint8_t settings_store_global_setting(uint8_t parameter, float value) {
198 if (value < 0.0) { return(STATUS_NEGATIVE_VALUE); }
199 if (parameter >= AXIS_SETTINGS_START_VAL) {
200 // Store axis configuration. Axis numbering sequence set by AXIS_SETTING defines.
201 // NOTE: Ensure the setting index corresponds to the report.c settings printout.
202 parameter -= AXIS_SETTINGS_START_VAL;
203 uint8_t set_idx = 0;
204 while (set_idx < AXIS_N_SETTINGS) {
205 if (parameter < N_AXIS) {
206 // Valid axis setting found.
207 switch (set_idx) {
208 case 0:
209 #ifdef MAX_STEP_RATE_HZ
210 if (value*settings.max_rate[parameter] > (MAX_STEP_RATE_HZ*60.0)) { return(STATUS_MAX_STEP_RATE_EXCEEDED); }
211 #endif
212 settings.steps_per_mm[parameter] = value;
213 break;
214 case 1:
215 #ifdef MAX_STEP_RATE_HZ
216 if (value*settings.steps_per_mm[parameter] > (MAX_STEP_RATE_HZ*60.0)) { return(STATUS_MAX_STEP_RATE_EXCEEDED); }
217 #endif
218 settings.max_rate[parameter] = value;
219 break;
220 case 2: settings.acceleration[parameter] = value*60*60; break; // Convert to mm/min^2 for grbl internal use.
221 case 3: settings.max_travel[parameter] = -value; break; // Store as negative for grbl internal use.
222 }
223 break; // Exit while-loop after setting has been configured and proceed to the EEPROM write call.
224 } else {
225 set_idx++;
226 // If axis index greater than N_AXIS or setting index greater than number of axis settings, error out.
227 if ((parameter < AXIS_SETTINGS_INCREMENT) || (set_idx == AXIS_N_SETTINGS)) { return(STATUS_INVALID_STATEMENT); }
228 parameter -= AXIS_SETTINGS_INCREMENT;
229 }
230 }
231 } else {
232 // Store non-axis Grbl settings
233 uint8_t int_value = trunc(value);
234 switch(parameter) {
235 case 0:
236 if (int_value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); }
237 settings.pulse_microseconds = int_value; break;
238 case 1: settings.stepper_idle_lock_time = int_value; break;
239 case 2:
240 settings.step_invert_mask = int_value;
241 st_generate_step_dir_invert_masks(); // Regenerate step and direction port invert masks.
242 break;
243 case 3:
244 settings.dir_invert_mask = int_value;
245 st_generate_step_dir_invert_masks(); // Regenerate step and direction port invert masks.
246 break;
247 case 4: // Reset to ensure change. Immediate re-init may cause problems.
248 if (int_value) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; }
249 else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; }
250 break;
251 case 5: // Reset to ensure change. Immediate re-init may cause problems.
252 if (int_value) { settings.flags |= BITFLAG_INVERT_LIMIT_PINS; }
253 else { settings.flags &= ~BITFLAG_INVERT_LIMIT_PINS; }
254 break;
255 case 6: // Reset to ensure change. Immediate re-init may cause problems.
256 if (int_value) { settings.flags |= BITFLAG_INVERT_PROBE_PIN; }
257 else { settings.flags &= ~BITFLAG_INVERT_PROBE_PIN; }
258 probe_configure_invert_mask(false);
259 break;
260 case 10: settings.status_report_mask = int_value; break;
261 case 11: settings.junction_deviation = value; break;
262 case 12: settings.arc_tolerance = value; break;
263 case 13:
264 if (int_value) { settings.flags |= BITFLAG_REPORT_INCHES; }
265 else { settings.flags &= ~BITFLAG_REPORT_INCHES; }
266 system_flag_wco_change(); // Make sure WCO is immediately updated.
267 break;
268 case 20:
269 if (int_value) {
270 if (bit_isfalse(settings.flags, BITFLAG_HOMING_ENABLE)) { return(STATUS_SOFT_LIMIT_ERROR); }
271 settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE;
272 } else { settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; }
273 break;
274 case 21:
275 if (int_value) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; }
276 else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; }
277 limits_init(); // Re-init to immediately change. NOTE: Nice to have but could be problematic later.
278 break;
279 case 22:
280 if (int_value) { settings.flags |= BITFLAG_HOMING_ENABLE; }
281 else {
282 settings.flags &= ~BITFLAG_HOMING_ENABLE;
283 settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; // Force disable soft-limits.
284 }
285 break;
286 case 23: settings.homing_dir_mask = int_value; break;
287 case 24: settings.homing_feed_rate = value; break;
288 case 25: settings.homing_seek_rate = value; break;
289 case 26: settings.homing_debounce_delay = int_value; break;
290 case 27: settings.homing_pulloff = value; break;
291 case 30: settings.rpm_max = value; spindle_init(); break; // Re-initialize spindle rpm calibration
292 case 31: settings.rpm_min = value; spindle_init(); break; // Re-initialize spindle rpm calibration
293 case 32:
294 #ifdef VARIABLE_SPINDLE
295 if (int_value) { settings.flags |= BITFLAG_LASER_MODE; }
296 else { settings.flags &= ~BITFLAG_LASER_MODE; }
297 #else
298 return(STATUS_SETTING_DISABLED_LASER);
299 #endif
300 break;
Luigi Santivetti42a1b332019-11-17 22:31:46 +0000301 #ifdef USE_ADC
302 case 33:
303 if (int_value) { settings.flags |= BITFLAG_ADC_ENABLE; }
304 else { settings.flags &= ~BITFLAG_ADC_ENABLE; }
305 break;
306 #endif
Luigi Santivetti69972f92019-11-12 22:55:40 +0000307 default:
308 return(STATUS_INVALID_STATEMENT);
309 }
310 }
311 write_global_settings();
312 return(STATUS_OK);
313}
314
315
316// Initialize the config subsystem
317void settings_init() {
318 if(!read_global_settings()) {
319 report_status_message(STATUS_SETTING_READ_FAIL);
320 settings_restore(SETTINGS_RESTORE_ALL); // Force restore all EEPROM data.
321 report_grbl_settings();
322 }
323}
324
325
326// Returns step pin mask according to Grbl internal axis indexing.
327uint8_t get_step_pin_mask(uint8_t axis_idx)
328{
329 if ( axis_idx == X_AXIS ) { return((1<<X_STEP_BIT)); }
330 if ( axis_idx == Y_AXIS ) { return((1<<Y_STEP_BIT)); }
331 return((1<<Z_STEP_BIT));
332}
333
334
335// Returns direction pin mask according to Grbl internal axis indexing.
336uint8_t get_direction_pin_mask(uint8_t axis_idx)
337{
338 if ( axis_idx == X_AXIS ) { return((1<<X_DIRECTION_BIT)); }
339 if ( axis_idx == Y_AXIS ) { return((1<<Y_DIRECTION_BIT)); }
340 return((1<<Z_DIRECTION_BIT));
341}
342
343
344// Returns limit pin mask according to Grbl internal axis indexing.
345uint8_t get_limit_pin_mask(uint8_t axis_idx)
346{
347 if ( axis_idx == X_AXIS ) { return((1<<X_LIMIT_BIT)); }
348 if ( axis_idx == Y_AXIS ) { return((1<<Y_LIMIT_BIT)); }
349 return((1<<Z_LIMIT_BIT));
350}