1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-09-02 10:53:01 +02:00

Merge branch 'Devt' into tapster_pro

This commit is contained in:
bdring
2020-10-02 11:26:18 -05:00
15 changed files with 261 additions and 169 deletions

View File

@@ -24,14 +24,29 @@ void memcpy_to_eeprom_with_checksum(unsigned int destination, const char* source
unsigned char checksum = 0;
for (; size > 0; size--) {
unsigned char data = static_cast<unsigned char>(*source++);
checksum = (checksum << 1) | (checksum >> 7);
// Note: This checksum calculation is broken as described below.
checksum = (checksum << 1) || (checksum >> 7);
checksum += data;
EEPROM.write(destination++, data);
EEPROM.write(destination++, *(source++));
}
EEPROM.write(destination, checksum);
EEPROM.commit();
}
int memcpy_from_eeprom_with_old_checksum(char* destination, unsigned int source, unsigned int size) {
unsigned char data, checksum = 0;
for (; size > 0; size--) {
data = EEPROM.read(source++);
// Note: This checksum calculation is broken - the || should be just | -
// thus making the checksum very weak.
// We leave it as-is so we can read old data after a firmware upgrade.
// The new storage format uses the tagged NVS mechanism, avoiding this bug.
checksum = (checksum << 1) || (checksum >> 7);
checksum += data;
*(destination++) = data;
}
return (checksum == EEPROM.read(source));
}
int memcpy_from_eeprom_with_checksum(char* destination, unsigned int source, unsigned int size) {
unsigned char data, checksum = 0;
for (; size > 0; size--) {

View File

@@ -26,3 +26,4 @@
//void eeprom_put_char(unsigned int addr, unsigned char new_value);
void memcpy_to_eeprom_with_checksum(unsigned int destination, const char* source, unsigned int size);
int memcpy_from_eeprom_with_checksum(char* destination, unsigned int source, unsigned int size);
int memcpy_from_eeprom_with_old_checksum(char* destination, unsigned int source, unsigned int size);

View File

@@ -40,6 +40,7 @@ std::map<Error, const char*> ErrorCodes = {
{ Error::TravelExceeded, "Max travel exceeded during jog" },
{ Error::InvalidJogCommand, "Invalid jog command" },
{ Error::SettingDisabledLaser, "Laser mode requires PWM output" },
{ Error::HomingNoCycles, "No Homing/Cycle defined in settings" },
{ Error::GcodeUnsupportedCommand, "Unsupported GCode command" },
{ Error::GcodeModalGroupViolation, "Gcode modal group violation" },
{ Error::GcodeUndefinedFeedRate, "Gcode undefined feed rate" },

View File

@@ -43,6 +43,7 @@ enum class Error : uint8_t {
TravelExceeded = 15,
InvalidJogCommand = 16,
SettingDisabledLaser = 17,
HomingNoCycles = 18,
GcodeUnsupportedCommand = 20,
GcodeModalGroupViolation = 21,
GcodeUndefinedFeedRate = 22,

View File

@@ -37,28 +37,11 @@ parser_block_t gc_block;
#define FAIL(status) return (status);
void gc_init() {
// First thing we do here is iterate through the coord systems and read them all, so that
// we get all our coord system errors here, and not while we're busy:
float coord_system[MAX_N_AXIS];
// g54 - g59 is 6 coordinate systems, plus 2 for G28 and G30 reference positions
bool reported_error = false;
const int MAX_COORD_SYSTEMS = 8;
for (uint8_t i = 0; i < MAX_COORD_SYSTEMS; ++i) {
if (!(settings_read_coord_data(i, coord_system))) {
if (!reported_error) {
reported_error = true;
report_status_message(Error::SettingReadFail, CLIENT_SERIAL);
}
}
}
// Reset parser state:
memset(&gc_state, 0, sizeof(parser_state_t));
// Load default G54 coordinate system.
if (!(settings_read_coord_data(gc_state.modal.coord_select, gc_state.coord_system))) {
report_status_message(Error::SettingReadFail, CLIENT_SERIAL);
}
gc_state.modal.coord_select = CoordIndex::G54;
coords[gc_state.modal.coord_select]->get(gc_state.coord_system);
}
// Sets g-code parser position in mm. Input in steps. Called by the system abort and hard
@@ -149,7 +132,7 @@ Error gc_execute_line(char* line, uint8_t client) {
memcpy(&gc_block.modal, &gc_state.modal, sizeof(gc_modal_t)); // Copy current modes
AxisCommand axis_command = AxisCommand::None;
uint8_t axis_0, axis_1, axis_linear;
uint8_t coord_select = 0; // Tracks G10 P coordinate selection for execution
CoordIndex coord_select = CoordIndex::G54; // Tracks G10 P coordinate selection for execution
// Initialize bitflag tracking variables for axis indices compatible operations.
uint8_t axis_words = 0; // XYZ tracking
uint8_t ijk_words = 0; // IJK tracking
@@ -158,6 +141,8 @@ Error gc_execute_line(char* line, uint8_t client) {
uint32_t value_words = 0; // Tracks value words.
uint8_t gc_parser_flags = GCParserNone;
auto n_axis = number_axis->get();
float coord_data[MAX_N_AXIS]; // Used by WCO-related commands
uint8_t pValue; // Integer value of P word
// Determine if the line is a jogging motion or a normal g-code block.
if (line[0] == '$') { // NOTE: `$J=` already parsed when passed to this function.
@@ -409,15 +394,30 @@ Error gc_execute_line(char* line, uint8_t client) {
mg_word_bit = ModalGroup::MG8;
break;
case 54:
case 55:
case 56:
case 57:
case 58:
case 59:
// NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.)
gc_block.modal.coord_select = int_value - 54; // Shift to array indexing.
gc_block.modal.coord_select = CoordIndex::G54;
mg_word_bit = ModalGroup::MG12;
break;
case 55:
gc_block.modal.coord_select = CoordIndex::G55;
mg_word_bit = ModalGroup::MG12;
break;
case 56:
gc_block.modal.coord_select = CoordIndex::G56;
mg_word_bit = ModalGroup::MG12;
break;
case 57:
gc_block.modal.coord_select = CoordIndex::G57;
mg_word_bit = ModalGroup::MG12;
break;
case 58:
gc_block.modal.coord_select = CoordIndex::G58;
mg_word_bit = ModalGroup::MG12;
break;
case 59:
gc_block.modal.coord_select = CoordIndex::G59;
mg_word_bit = ModalGroup::MG12;
break;
// NOTE: G59.x are not supported.
case 61:
if (mantissa != 0) {
FAIL(Error::GcodeUnsupportedCommand); // [G61.1 not supported]
@@ -879,13 +879,13 @@ Error gc_execute_line(char* line, uint8_t client) {
float block_coord_system[MAX_N_AXIS];
memcpy(block_coord_system, gc_state.coord_system, sizeof(gc_state.coord_system));
if (bit_istrue(command_words, bit(ModalGroup::MG12))) { // Check if called in block
if (gc_block.modal.coord_select > N_COORDINATE_SYSTEM) {
// This error probably cannot happen because preceding code sets
// gc_block.modal.coord_select only to specific supported values
if (gc_block.modal.coord_select >= CoordIndex::NWCSystems) {
FAIL(Error::GcodeUnsupportedCoordSys); // [Greater than N sys]
}
if (gc_state.modal.coord_select != gc_block.modal.coord_select) {
if (!(settings_read_coord_data(gc_block.modal.coord_select, block_coord_system))) {
FAIL(Error::SettingReadFail);
}
coords[gc_block.modal.coord_select]->get(block_coord_system);
}
}
// [16. Set path control mode ]: N/A. Only G61. G61.1 and G64 NOT SUPPORTED.
@@ -907,10 +907,6 @@ Error gc_execute_line(char* line, uint8_t client) {
if (bit_isfalse(value_words, (bit(GCodeWord::P) | bit(GCodeWord::L)))) {
FAIL(Error::GcodeValueWordMissing); // [P/L word missing]
}
coord_select = trunc(gc_block.values.p); // Convert p value to int.
if (coord_select > N_COORDINATE_SYSTEM) {
FAIL(Error::GcodeUnsupportedCoordSys); // [Greater than N sys]
}
if (gc_block.values.l != 20) {
if (gc_block.values.l == 2) {
if (bit_istrue(value_words, bit(GCodeWord::R))) {
@@ -920,18 +916,21 @@ Error gc_execute_line(char* line, uint8_t client) {
FAIL(Error::GcodeUnsupportedCommand); // [Unsupported L]
}
}
bit_false(value_words, (bit(GCodeWord::L) | bit(GCodeWord::P)));
// Determine coordinate system to change and try to load from EEPROM.
if (coord_select > 0) {
coord_select--; // Adjust P1-P6 index to EEPROM coordinate data indexing.
// Select the coordinate system based on the P word
pValue = trunc(gc_block.values.p); // Convert p value to integer
if (pValue > 0) {
// P1 means G54, P2 means G55, etc.
coord_select = static_cast<CoordIndex>(pValue - 1 + CoordIndex::G54);
} else {
coord_select = gc_block.modal.coord_select; // Index P0 as the active coordinate system
// P0 means use currently-selected system
coord_select = gc_block.modal.coord_select;
}
// NOTE: Store parameter data in IJK values. By rule, they are not in use with this command.
// FIXME: Instead of IJK, we'd better use: float vector[MAX_N_AXIS]; // [DG]
if (!settings_read_coord_data(coord_select, gc_block.values.ijk)) {
FAIL(Error::SettingReadFail); // [EEPROM read fail]
if (coord_select >= CoordIndex::NWCSystems) {
FAIL(Error::GcodeUnsupportedCoordSys); // [Greater than N sys]
}
bit_false(value_words, (bit(GCodeWord::L) | bit(GCodeWord::P)));
coords[coord_select]->get(coord_data);
// Pre-calculate the coordinate data changes.
for (idx = 0; idx < n_axis; idx++) { // Axes indices are consistent, so loop may be used.
// Update axes defined only in block. Always in machine coordinates. Can change non-active system.
@@ -939,13 +938,13 @@ Error gc_execute_line(char* line, uint8_t client) {
if (gc_block.values.l == 20) {
// L20: Update coordinate system axis at current position (with modifiers) with programmed value
// WPos = MPos - WCS - G92 - TLO -> WCS = MPos - G92 - TLO - WPos
gc_block.values.ijk[idx] = gc_state.position[idx] - gc_state.coord_offset[idx] - gc_block.values.xyz[idx];
coord_data[idx] = gc_state.position[idx] - gc_state.coord_offset[idx] - gc_block.values.xyz[idx];
if (idx == TOOL_LENGTH_OFFSET_AXIS) {
gc_block.values.ijk[idx] -= gc_state.tool_length_offset;
coord_data[idx] -= gc_state.tool_length_offset;
}
} else {
// L2: Update coordinate system axis to programmed value.
gc_block.values.ijk[idx] = gc_block.values.xyz[idx];
coord_data[idx] = gc_block.values.xyz[idx];
}
} // Else, keep current stored value.
}
@@ -1003,37 +1002,16 @@ Error gc_execute_line(char* line, uint8_t client) {
case NonModal::GoHome1: // G30
// [G28/30 Errors]: Cutter compensation is enabled.
// Retreive G28/30 go-home position data (in machine coordinates) from EEPROM
// NOTE: Store parameter data in IJK values. By rule, they are not in use with this command.
if (gc_block.non_modal_command == NonModal::GoHome0) {
#ifdef USE_KINEMATICS_FOO
// read the data into a temporary array, so we can apply kinematics
float G28_Pos[MAX_N_AXIS];
if (!settings_read_coord_data(SETTING_INDEX_G28, G28_Pos)) {
FAIL(Error::SettingReadFail);
}
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "G28 Cartesian: %3.3f %3.3f %3.3f", G28_Pos[0], G28_Pos[1], G28_Pos[2]);
inverse_kinematics(G28_Pos); // change G28_Pos from cartesian to angles
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "G28 Angle: %3.3f %3.3f %3.3f", G28_Pos[0], G28_Pos[1], G28_Pos[2]);
memcpy(gc_block.values.ijk, G28_Pos, sizeof(G28_Pos));
memcpy(gc_state.position, G28_Pos, sizeof(G28_Pos)); // update position for next move reference
mc_line_kins(G28_Pos, pl_data , gc_state.position);
#else
if (!settings_read_coord_data(SETTING_INDEX_G28, gc_block.values.ijk)) {
FAIL(Error::SettingReadFail);
}
#endif
coords[CoordIndex::G28]->get(coord_data);
} else { // == NonModal::GoHome1
if (!settings_read_coord_data(SETTING_INDEX_G30, gc_block.values.ijk)) {
FAIL(Error::SettingReadFail);
}
coords[CoordIndex::G30]->get(coord_data);
}
if (axis_words) {
// Move only the axes specified in secondary move.
for (idx = 0; idx < n_axis; idx++) {
if (!(axis_words & bit(idx))) {
gc_block.values.ijk[idx] = gc_state.position[idx];
coord_data[idx] = gc_state.position[idx];
}
}
} else {
@@ -1470,7 +1448,7 @@ Error gc_execute_line(char* line, uint8_t client) {
// [15. Coordinate system selection ]:
if (gc_state.modal.coord_select != gc_block.modal.coord_select) {
gc_state.modal.coord_select = gc_block.modal.coord_select;
memcpy(gc_state.coord_system, block_coord_system, MAX_N_AXIS * sizeof(float));
memcpy(gc_state.coord_system, block_coord_system, sizeof(gc_state.coord_system));
system_flag_wco_change();
}
// [16. Set path control mode ]: G61.1/G64 NOT SUPPORTED
@@ -1481,10 +1459,10 @@ Error gc_execute_line(char* line, uint8_t client) {
// [19. Go to predefined position, Set G10, or Set axis offsets ]:
switch (gc_block.non_modal_command) {
case NonModal::SetCoordinateData:
settings_write_coord_data(coord_select, gc_block.values.ijk);
coords[coord_select]->set(coord_data);
// Update system coordinate system if currently active.
if (gc_state.modal.coord_select == coord_select) {
memcpy(gc_state.coord_system, gc_block.values.ijk, MAX_N_AXIS * sizeof(float));
memcpy(gc_state.coord_system, coord_data, sizeof(gc_state.coord_system));
system_flag_wco_change();
}
break;
@@ -1496,14 +1474,14 @@ Error gc_execute_line(char* line, uint8_t client) {
if (axis_command != AxisCommand::None) {
mc_line(gc_block.values.xyz, pl_data); // kinematics kinematics not used for homing righ now
}
mc_line_kins(gc_block.values.ijk, pl_data, gc_state.position);
memcpy(gc_state.position, gc_block.values.ijk, MAX_N_AXIS * sizeof(float));
mc_line(coord_data, pl_data);
memcpy(gc_state.position, coord_data, sizeof(gc_state.position));
break;
case NonModal::SetHome0:
settings_write_coord_data(SETTING_INDEX_G28, gc_state.position);
coords[CoordIndex::G28]->set(gc_state.position);
break;
case NonModal::SetHome1:
settings_write_coord_data(SETTING_INDEX_G30, gc_state.position);
coords[CoordIndex::G30]->set(gc_state.position);
break;
case NonModal::SetCoordinateOffset:
memcpy(gc_state.coord_offset, gc_block.values.xyz, sizeof(gc_block.values.xyz));
@@ -1603,7 +1581,7 @@ Error gc_execute_line(char* line, uint8_t client) {
gc_state.modal.distance = Distance::Absolute;
gc_state.modal.feed_rate = FeedRate::UnitsPerMin;
// gc_state.modal.cutter_comp = CutterComp::Disable; // Not supported.
gc_state.modal.coord_select = 0; // G54
gc_state.modal.coord_select = CoordIndex::G54;
gc_state.modal.spindle = SpindleState::Disable;
gc_state.modal.coolant = {};
#ifdef ENABLE_PARKING_OVERRIDE_CONTROL
@@ -1621,9 +1599,7 @@ Error gc_execute_line(char* line, uint8_t client) {
#endif
// Execute coordinate change and spindle/coolant stop.
if (sys.state != State::CheckMode) {
if (!(settings_read_coord_data(gc_state.modal.coord_select, gc_state.coord_system))) {
FAIL(Error::SettingReadFail);
}
coords[gc_state.modal.coord_select]->get(gc_state.coord_system);
system_flag_wco_change(); // Set to refresh immediately just in case something altered.
spindle->set_state(SpindleState::Disable, 0);
coolant_off();

View File

@@ -251,7 +251,7 @@ typedef struct {
Plane plane_select; // {G17,G18,G19}
// CutterCompensation cutter_comp; // {G40} NOTE: Don't track. Only default supported.
ToolLengthOffset tool_length; // {G43.1,G49}
uint8_t coord_select; // {G54,G55,G56,G57,G58,G59}
CoordIndex coord_select; // {G54,G55,G56,G57,G58,G59}
// uint8_t control; // {G61} NOTE: Don't track. Only default supported.
ProgramFlow program_flow; // {M0,M1,M2,M30}
CoolantState coolant; // {M7,M8,M9}
@@ -264,7 +264,7 @@ typedef struct {
typedef struct {
uint8_t e; // M67
float f; // Feed
float ijk[MAX_N_AXIS]; // I,J,K Axis arc offsets
float ijk[3]; // I,J,K Axis arc offsets - only 3 are possible
uint8_t l; // G10 or canned cycles parameters
int32_t n; // Line number
float p; // G10 or dwell parameters

View File

@@ -23,7 +23,7 @@
// Grbl versioning system
const char* const GRBL_VERSION = "1.3a";
const char* const GRBL_VERSION_BUILD = "20200924";
const char* const GRBL_VERSION_BUILD = "20200929";
//#include <sdkconfig.h>
#include <Arduino.h>

View File

@@ -264,7 +264,7 @@ static bool axis_is_squared(uint8_t axis_mask) {
// NOTE: There should be no motions in the buffer and Grbl must be in an idle state before
// executing the homing cycle. This prevents incorrect buffered plans after homing.
void mc_homing_cycle(uint8_t cycle_mask) {
bool no_cycle_defined = true; // this will catch if no homing cycle has been defined
bool no_cycles_defined = true;
#ifdef USE_CUSTOM_HOMING
if (user_defined_homing()) {
return;
@@ -317,7 +317,7 @@ void mc_homing_cycle(uint8_t cycle_mask) {
for (int cycle = 0; cycle < MAX_N_AXIS; cycle++) {
auto homing_mask = homing_cycle[cycle]->get();
if (homing_mask) { // if there are some axes in this cycle
no_cycle_defined = false;
no_cycles_defined = false;
if (!axis_is_squared(homing_mask)) {
limits_go_home(homing_mask); // Homing cycle 0
} else {
@@ -333,8 +333,8 @@ void mc_homing_cycle(uint8_t cycle_mask) {
}
}
}
if (no_cycle_defined) {
if (no_cycles_defined) {
report_status_message(Error::HomingNoCycles, CLIENT_ALL);
}
}
protocol_execute_realtime(); // Check for reset and set system abort.

View File

@@ -56,11 +56,8 @@ void settings_restore(uint8_t restore_flag) {
}
}
if (restore_flag & SETTINGS_RESTORE_PARAMETERS) {
uint8_t idx;
float coord_data[MAX_N_AXIS];
memset(&coord_data, 0, sizeof(coord_data));
for (idx = 0; idx <= SETTING_INDEX_NCOORD; idx++) {
settings_write_coord_data(idx, coord_data);
for (auto idx = CoordIndex::Begin; idx < CoordIndex::End; ++idx) {
coords[idx]->setDefault();
}
}
if (restore_flag & SETTINGS_RESTORE_BUILD_INFO) {
@@ -559,8 +556,10 @@ Error system_execute_line(char* line, WebUI::ESPResponseStream* out, WebUI::Auth
// non-empty string - [ESPxxx]yyy or $xxx=yyy
return do_command_or_setting(key, value, auth_level, out);
}
Error system_execute_line(char* line, uint8_t client, WebUI::AuthenticationLevel auth_level) {
return system_execute_line(line, new WebUI::ESPResponseStream(client, true), auth_level);
WebUI::ESPResponseStream stream(client, true);
return system_execute_line(line, &stream, auth_level);
}
void system_execute_startup(char* line) {

View File

@@ -166,23 +166,24 @@ void grbl_notifyf(const char* title, const char* format, ...) {
}
}
static const int coordStringLen = 20;
static const int axesStringLen = coordStringLen * MAX_N_AXIS;
// formats axis values into a string and returns that string in rpt
// NOTE: rpt should have at least size: 20 * MAX_N_AXIS
// NOTE: rpt should have at least size: axesStringLen
static void report_util_axis_values(float* axis_value, char* rpt) {
uint8_t idx;
char axisVal[20];
char axisVal[coordStringLen];
float unit_conv = 1.0; // unit conversion multiplier..default is mm
const char* format = "%4.3f"; // Default - report mm to 3 decimal places
rpt[0] = '\0';
if (report_inches->get()) {
unit_conv = 1.0 / MM_PER_INCH;
format = "%4.4f"; // Report inches to 4 decimal places
}
auto n_axis = number_axis->get();
for (idx = 0; idx < n_axis; idx++) {
if (report_inches->get()) {
snprintf(axisVal, 19, "%4.4f", axis_value[idx] * unit_conv); // Report inches to 4 decimals
} else {
snprintf(axisVal, 19, "%4.3f", axis_value[idx] * unit_conv); // Report mm to 3 decimals
}
snprintf(axisVal, coordStringLen-1, format, axis_value[idx] * unit_conv);
strcat(rpt, axisVal);
if (idx < (number_axis->get() - 1)) {
strcat(rpt, ",");
@@ -190,6 +191,27 @@ static void report_util_axis_values(float* axis_value, char* rpt) {
}
}
// This version returns the axis values as a String
static String report_util_axis_values(const float* axis_value) {
String rpt = "";
uint8_t idx;
char axisVal[coordStringLen];
float unit_conv = 1.0; // unit conversion multiplier..default is mm
int decimals = 3; // Default - report mm to 3 decimal places
if (report_inches->get()) {
unit_conv = 1.0 / MM_PER_INCH;
decimals = 4; // Report inches to 4 decimal places
}
auto n_axis = number_axis->get();
for (idx = 0; idx < n_axis; idx++) {
rpt += String(axis_value[idx] * unit_conv, decimals);
if (idx < (number_axis->get() - 1)) {
rpt += ",";
}
}
return rpt;
}
// Handles the primary confirmation protocol response for streaming interfaces and human-feedback.
// For every incoming line, this method responds with an 'ok' for a successful command or an
// 'error:' to indicate some error event with the line or some critical system error during
@@ -284,8 +306,8 @@ void report_grbl_help(uint8_t client) {
void report_probe_parameters(uint8_t client) {
// Report in terms of machine position.
float print_position[MAX_N_AXIS];
char probe_rpt[(MAX_N_AXIS * 20 + 13 + 6 + 1)]; // the probe report we are building here
char temp[MAX_N_AXIS * 20];
char probe_rpt[(axesStringLen + 13 + 6 + 1)]; // the probe report we are building here
char temp[axesStringLen];
strcpy(probe_rpt, "[PRB:"); // initialize the string with the first characters
// get the machine position and put them into a string and append to the probe report
system_convert_array_steps_to_mpos(print_position, sys_probe_position);
@@ -299,46 +321,27 @@ void report_probe_parameters(uint8_t client) {
// Prints Grbl NGC parameters (coordinate offsets, probing)
void report_ngc_parameters(uint8_t client) {
float coord_data[MAX_N_AXIS];
uint8_t coord_select;
char temp[MAX_N_AXIS * 20];
char ngc_rpt[((8 + (MAX_N_AXIS * 20)) * SETTING_INDEX_NCOORD + 4 + MAX_N_AXIS * 20 + 8 + 2 * 20)];
ngc_rpt[0] = '\0';
for (coord_select = 0; coord_select <= SETTING_INDEX_NCOORD; coord_select++) {
if (!(settings_read_coord_data(coord_select, coord_data))) {
report_status_message(Error::SettingReadFail, CLIENT_SERIAL);
return;
String ngc_rpt = "";
// Print persistent offsets G54 - G59, G28, and G30
for (auto coord_select = CoordIndex::Begin; coord_select < CoordIndex::End; ++coord_select) {
ngc_rpt += "[";
ngc_rpt += coords[coord_select]->getName();
ngc_rpt += ":";
ngc_rpt += report_util_axis_values(coords[coord_select]->get());
ngc_rpt += "]\r\n";
}
strcat(ngc_rpt, "[G");
switch (coord_select) {
case 6:
strcat(ngc_rpt, "28");
break;
case 7:
strcat(ngc_rpt, "30");
break;
default:
sprintf(temp, "%d", coord_select + 54);
strcat(ngc_rpt, temp);
break; // G54-G59
}
strcat(ngc_rpt, ":");
report_util_axis_values(coord_data, temp);
strcat(ngc_rpt, temp);
strcat(ngc_rpt, "]\r\n");
}
strcat(ngc_rpt, "[G92:"); // Print G92,G92.1 which are not persistent in memory
report_util_axis_values(gc_state.coord_offset, temp);
strcat(ngc_rpt, temp);
strcat(ngc_rpt, "]\r\n");
strcat(ngc_rpt, "[TLO:"); // Print tool length offset value
ngc_rpt += "[G92:"; // Print non-persistent G92,G92.1
ngc_rpt += report_util_axis_values(gc_state.coord_offset);
ngc_rpt += "]\r\n";
ngc_rpt += "[TLO:"; // Print tool length offset
float tlo = gc_state.tool_length_offset;
if (report_inches->get()) {
snprintf(temp, 20, "%4.3f]\r\n", gc_state.tool_length_offset * INCH_PER_MM);
} else {
snprintf(temp, 20, "%4.3f]\r\n", gc_state.tool_length_offset);
tlo *= INCH_PER_MM;
}
strcat(ngc_rpt, temp);
grbl_send(client, ngc_rpt);
ngc_rpt += String(tlo, 3);;
ngc_rpt += "]\r\n";
grbl_send(client, ngc_rpt.c_str());
report_probe_parameters(client);
}

View File

@@ -653,3 +653,32 @@ Error GrblCommand::action(char* value, WebUI::AuthenticationLevel auth_level, We
}
return _action((const char*)value, auth_level, out);
};
Coordinates* coords[CoordIndex::End];
bool Coordinates::load() {
size_t len;
switch (nvs_get_blob(Setting::_handle, _name, _currentValue, &len)) {
case ESP_OK:
return true;
case ESP_ERR_NVS_INVALID_LENGTH:
// This could happen if the stored value is longer than the buffer.
// That is highly unlikely since we always store MAX_N_AXIS coordinates.
// It would indicate that we have decreased MAX_N_AXIS since the
// value was stored. We don't flag it as an error, but rather
// accept the initial coordinates and ignore the residue.
// We could issue a warning message if we were so inclined.
return true;
case ESP_ERR_NVS_INVALID_NAME:
case ESP_ERR_NVS_INVALID_HANDLE:
default:
return false;
}
};
void Coordinates::set(float value[MAX_N_AXIS]) {
memcpy(&_currentValue, value, sizeof(_currentValue));
#ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE
protocol_buffer_synchronize();
#endif
nvs_set_blob(Setting::_handle, _name, _currentValue, sizeof(_currentValue));
}

View File

@@ -76,7 +76,6 @@ public:
class Setting : public Word {
private:
protected:
static nvs_handle _handle;
// group_t _group;
axis_t _axis = NO_AXIS;
Setting* link; // linked list of setting objects
@@ -85,6 +84,7 @@ protected:
const char* _keyName;
public:
static nvs_handle _handle;
static void init();
static Setting* List;
Setting* next() { return link; }
@@ -206,6 +206,28 @@ public:
int32_t get() { return _currentValue; }
};
class Coordinates {
private:
float _currentValue[MAX_N_AXIS];
const char* _name;
public:
Coordinates(const char* name) : _name(name) {}
const char* getName() { return _name; }
bool load();
void setDefault() {
float zeros[MAX_N_AXIS] = { 0.0, };
set(zeros);
};
// Copy the value to an array
void get(float* value) { memcpy(value, _currentValue, sizeof(_currentValue)); }
// Return a pointer to the array
const float* get() { return _currentValue; }
void set(float *value);
};
extern Coordinates* coords[CoordIndex::End];
class FloatSetting : public Setting {
private:
float _defaultValue;

View File

@@ -205,9 +205,38 @@ static const char* makeGrblName(int axisNum, int base) {
return strcpy(retval, buf);
}
void make_coordinate(CoordIndex index, const char* name) {
float coord_data[MAX_N_AXIS] = { 0.0 };
auto coord = new Coordinates(name);
coords[index] = coord;
if (!coord->load()) {
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Propagating %s data to NVS format", coord->getName());
// If coord->load() returns false it means that no entry
// was present in non-volatile storage. In that case we
// first look for an old-format entry in the EEPROM section.
// If an entry is present some number of float values at
// the beginning of coord_data will be overwritten with
// the EEPROM data, and the rest will remain at 0.0.
// If no old-format entry is present, all will remain 0.0
// Regardless, we create a new entry with that data.
(void)old_settings_read_coord_data(index, coord_data);
coords[index]->set(coord_data);
}
}
void make_settings() {
Setting::init();
// Propagate old coordinate system data to the new format if necessary.
// G54 - G59 work coordinate systems, G28, G30 reference positions, etc
make_coordinate(CoordIndex::G54, "G54");
make_coordinate(CoordIndex::G55, "G55");
make_coordinate(CoordIndex::G56, "G56");
make_coordinate(CoordIndex::G57, "G57");
make_coordinate(CoordIndex::G58, "G58");
make_coordinate(CoordIndex::G59, "G59");
make_coordinate(CoordIndex::G28, "G28");
make_coordinate(CoordIndex::G30, "G30");
// number_axis = new IntSetting(EXTENDED, WG, NULL, "NumberAxis", N_AXIS, 0, 6, NULL, true);
number_axis = new FakeSetting<int>(N_AXIS);

View File

@@ -25,26 +25,21 @@
#include "Grbl.h"
// Read selected coordinate data from EEPROM. Updates pointed coord_data value.
uint8_t settings_read_coord_data(uint8_t coord_select, float* coord_data) {
uint32_t addr = coord_select * (sizeof(float) * MAX_N_AXIS + 1) + EEPROM_ADDR_PARAMETERS;
if (!(memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float) * MAX_N_AXIS))) {
// This is now a compatibility routine that is used to propagate coordinate data
// in the old EEPROM format to the new tagged NVS format.
bool old_settings_read_coord_data(uint8_t coord_select, float* coord_data) {
uint32_t addr = coord_select * (sizeof(float) * N_AXIS + 1) + EEPROM_ADDR_PARAMETERS;
if (!(memcpy_from_eeprom_with_old_checksum((char*)coord_data, addr, sizeof(float) * N_AXIS)) &&
!(memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float) * MAX_N_AXIS))) {
// Reset with default zero vector
clear_vector_float(coord_data);
settings_write_coord_data(coord_select, coord_data);
// The old code used to rewrite the zeroed data but now that is done
// elsewhere, in a different format.
return false;
}
return true;
}
// Method to store coord data parameters into EEPROM
void settings_write_coord_data(uint8_t coord_select, float* coord_data) {
#ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE
protocol_buffer_synchronize();
#endif
uint32_t addr = coord_select * (sizeof(float) * MAX_N_AXIS + 1) + EEPROM_ADDR_PARAMETERS;
memcpy_to_eeprom_with_checksum(addr, (char*)coord_data, sizeof(float) * MAX_N_AXIS);
}
// Method to store build info into EEPROM
// NOTE: This function can only be called in IDLE state.
void settings_store_build_info(const char* line) {
@@ -73,3 +68,9 @@ uint8_t get_step_pin_mask(uint8_t axis_idx) {
uint8_t get_direction_pin_mask(uint8_t axis_idx) {
return bit(axis_idx);
}
// Allow iteration over CoordIndex values
CoordIndex& operator ++ (CoordIndex& i) {
i = static_cast<CoordIndex>(static_cast<uint8_t>(i) + 1);
return i;
}

View File

@@ -48,14 +48,6 @@ const int EEPROM_SIZE = 1024U;
const int EEPROM_ADDR_PARAMETERS = 512U;
const int EEPROM_ADDR_BUILD_INFO = 942U;
// Define EEPROM address indexing for coordinate parameters
const int N_COORDINATE_SYSTEM = 6; // Number of supported work coordinate systems (from index 1)
const int SETTING_INDEX_NCOORD = N_COORDINATE_SYSTEM + 1; // Total number of system stored (from index 0)
// NOTE: Work coordinate indices are (0=G54, 1=G55, ... , 6=G59)
const int SETTING_INDEX_G28 = N_COORDINATE_SYSTEM; // Home position 1
const int SETTING_INDEX_G30 = N_COORDINATE_SYSTEM + 1; // Home position 2
// const int SETTING_INDEX_G92 = N_COORDINATE_SYSTEM+2; // Coordinate offset (G92.2,G92.3 not supported)
// Initialize the configuration subsystem (load settings from EEPROM)
void settings_init();
void settings_restore(uint8_t restore_flag);
@@ -64,14 +56,37 @@ void write_global_settings();
uint8_t settings_read_build_info(char* line);
void settings_store_build_info(const char* line);
// Writes selected coordinate data to EEPROM
void settings_write_coord_data(uint8_t coord_select, float* coord_data);
// Reads selected coordinate data from EEPROM
uint8_t settings_read_coord_data(uint8_t coord_select, float* coord_data);
bool old_settings_read_coord_data(uint8_t coord_select, float* coord_data);
// Returns the step pin mask according to Grbl's internal axis numbering
uint8_t get_step_pin_mask(uint8_t i);
// Returns the direction pin mask according to Grbl's internal axis numbering
uint8_t get_direction_pin_mask(uint8_t i);
// Various places in the code access saved coordinate system data
// by a small integer index according to the values below.
enum CoordIndex : uint8_t{
Begin = 0,
G54 = Begin,
G55,
G56,
G57,
G58,
G59,
// To support 9 work coordinate systems it would be necessary to define
// the following 3 and modify GCode.cpp to support G59.1, G59.2, G59.3
// G59_1,
// G59_2,
// G59_3,
NWCSystems,
G28 = NWCSystems,
G30,
// G92_2,
// G92_3,
End,
};
// Allow iteration over CoordIndex values
CoordIndex& operator ++ (CoordIndex& i);