test check in

This commit is contained in:
Terje Io
2021-02-22 12:29:17 +01:00
commit cdca5ad55c
61 changed files with 20794 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
# Auto detect text files and perform LF normalization
* text=auto eol=lf
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
+43
View File
@@ -0,0 +1,43 @@
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# Subversion folders
.svn
# Eclipse folders
.settings
# STM32 .ioc files
*.ioc
# Build folder
build
#
# =========================
# Operating System Files
# =========================
.vscode/settings.json
.vscode/c_cpp_properties.json
+76
View File
@@ -0,0 +1,76 @@
/*
alarms.h -
Part of grblHAL
Copyright (c) 2017-2021 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _ALARMS_H_
#define _ALARMS_H_
// Alarm executor codes. Valid values (1-255). Zero is reserved.
typedef enum {
Alarm_None = 0,
Alarm_HardLimit = 1,
Alarm_SoftLimit = 2,
Alarm_AbortCycle = 3,
Alarm_ProbeFailInitial = 4,
Alarm_ProbeFailContact = 5,
Alarm_HomingFailReset = 6,
Alarm_HomingFailDoor = 7,
Alarm_FailPulloff = 8,
Alarm_HomingFailApproach = 9,
Alarm_EStop = 10,
Alarm_HomingRequried = 11,
Alarm_LimitsEngaged = 12,
Alarm_ProbeProtect = 13,
Alarm_Spindle = 14,
Alarm_HomingFailAutoSquaringApproach = 15,
Alarm_SelftestFailed = 16,
Alarm_MotorFault = 17
} alarm_code_t;
typedef struct {
alarm_code_t id;
const char *name;
const char *description;
} alarm_detail_t;
PROGMEM static const alarm_detail_t alarm_detail[] = {
{ Alarm_HardLimit, "Hard limit", "Hard limit has been triggered. Machine position is likely lost due to sudden halt. Re-homing is highly recommended." },
{ Alarm_SoftLimit, "Soft limit", "Soft limit alarm. G-code motion target exceeds machine travel. Machine position retained. Alarm may be safely unlocked." },
{ Alarm_AbortCycle, "Abort during cycle", "Reset while in motion. Machine position is likely lost due to sudden halt. Re-homing is highly recommended." },
{ Alarm_ProbeFailInitial, "Probe fail", "Probe fail. Probe is not in the expected initial state before starting probe cycle when G38.2 and G38.3 is not triggered and G38.4 and G38.5 is triggered." },
{ Alarm_ProbeFailContact, "Probe fail", "Probe fail. Probe did not contact the workpiece within the programmed travel for G38.2 and G38.4." },
{ Alarm_HomingFailReset, "Homing fail", "Homing fail. The active homing cycle was reset." },
{ Alarm_HomingFailDoor, "Homing fail", "Homing fail. Safety door was opened during homing cycle." },
{ Alarm_FailPulloff, "Homing fail", "Homing fail. Pull off travel failed to clear limit switch. Try increasing pull-off setting or check wiring." },
{ Alarm_HomingFailApproach, "Homing fail", "Homing fail. Could not find limit switch within search distances. Try increasing max travel, decreasing pull-off distance, or check wiring." },
{ Alarm_EStop, "EStop", "EStop asserted. Clear and reset" },
{ Alarm_HomingRequried, "Homing required", "Homing required. Execute homing command ($H) to continue." },
{ Alarm_LimitsEngaged, "Limit switch engaged", "Limit switch engaged. Clear before continuing." },
{ Alarm_ProbeProtect, "Probe protection triggered", "Probe protection triggered. Clear before continuing." },
{ Alarm_Spindle, "Spindle at speed timeout", "Spindle at speed timeout. Clear before continuing." },
{ Alarm_HomingFailAutoSquaringApproach, "Homing fail", "Homing fail. Could not find second limit switch for auto squared axis within search distances. Try increasing max travel, decreasing pull-off distance, or check wiring." },
{ Alarm_SelftestFailed, "Selftest failed", "Power on selftest (POS) failed." },
{ Alarm_MotorFault, "Motor fault", "Motor fault." }
};
#endif
+614
View File
File diff suppressed because it is too large Load Diff
+55
View File
@@ -0,0 +1,55 @@
/*
coolant_control.c - coolant control methods
Part of grblHAL
Copyright (c) 2016-2021 Terje Io
Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC
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 <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
#include "hal.h"
#include "protocol.h"
#include "coolant_control.h"
#include "state_machine.h"
// Main program only. Immediately sets flood coolant running state and also mist coolant,
// if enabled. Also sets a flag to report an update to a coolant state.
// Called by coolant toggle override, parking restore, parking retract, sleep mode, g-code
// parser program end, and g-code parser coolant_sync().
void coolant_set_state (coolant_state_t mode)
{
if (!ABORTED) { // Block during abort.
hal.coolant.set_state(mode);
sys.report.coolant = On; // Set to report change immediately
}
}
// G-code parser entry-point for setting coolant state. Forces a planner buffer sync and bails
// if an abort or check-mode is active.
bool coolant_sync (coolant_state_t mode)
{
bool ok = true;
if (state_get() != STATE_CHECK_MODE) {
if((ok = protocol_buffer_synchronize())) // Ensure coolant changes state when specified in program.
coolant_set_state(mode);
}
return ok;
}
+46
View File
@@ -0,0 +1,46 @@
/*
coolant_control.h - spindle control methods
Part of grblHAL
Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _COOLANT_CONTROL_H_
#define _COOLANT_CONTROL_H_
typedef union {
uint8_t value;
uint8_t mask;
struct {
uint8_t flood :1,
mist :1,
shower :1,
trough_spindle :1,
reserved4 :1,
reserved5 :1,
reserved6 :1,
reserved7 :1;
};
} coolant_state_t;
// Sets the coolant pins according to state specified.
void coolant_set_state(coolant_state_t mode);
// G-code parser entry-point for setting coolant states. Checks for and executes additional conditions.
bool coolant_sync(coolant_state_t mode);
#endif
+166
View File
@@ -0,0 +1,166 @@
/*
corexy.c - corexy kinematics implementation
Part of grblHAL
Copyright (c) 2019 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
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 <http://www.gnu.org/licenses/>.
*/
#include "grbl.h"
#ifdef COREXY
#include "settings.h"
#include "planner.h"
#include "kinematics.h"
// CoreXY motor assignments. DO NOT ALTER.
// NOTE: If the A and B motor axis bindings are changed, this effects the CoreXY equations.
#define A_MOTOR X_AXIS // Must be X_AXIS
#define B_MOTOR Y_AXIS // Must be Y_AXIS
// Returns x or y-axis "steps" based on CoreXY motor steps.
inline static int32_t corexy_convert_to_a_motor_steps (int32_t *steps)
{
return (steps[A_MOTOR] + steps[B_MOTOR]) >> 1;
}
inline static int32_t corexy_convert_to_b_motor_steps (int32_t *steps)
{
return (steps[A_MOTOR] - steps[B_MOTOR]) >> 1;
}
// Returns machine position of axis 'idx'. Must be sent a 'step' array.
static void corexy_convert_array_steps_to_mpos (float *position, int32_t *steps)
{
position[X_AXIS] = corexy_convert_to_a_motor_steps(steps) / settings.axis[X_AXIS].steps_per_mm;
position[Y_AXIS] = corexy_convert_to_b_motor_steps(steps) / settings.axis[Y_AXIS].steps_per_mm;
position[Z_AXIS] = steps[Z_AXIS] / settings.axis[Z_AXIS].steps_per_mm;
}
// Transform absolute position from cartesian coordinate system (mm) to corexy coordinate system (step)
static void corexy_target_to_steps (int32_t *target_steps, float *target)
{
uint_fast8_t idx = N_AXIS;
int32_t a_steps, b_steps;
do {
switch(--idx) {
case X_AXIS:
a_steps = lroundf(target[idx] * settings.axis[idx].steps_per_mm);
break;
case Y_AXIS:
b_steps = lroundf(target[idx] * settings.axis[idx].steps_per_mm);
break;
default:
target_steps[idx] = lroundf(target[idx] * settings.axis[idx].steps_per_mm);
break;
}
} while(idx);
target_steps[A_MOTOR] = a_steps + b_steps;
target_steps[B_MOTOR] = a_steps - b_steps;
}
static uint_fast8_t corexy_limits_get_axis_mask (uint_fast8_t idx)
{
return ((idx == A_MOTOR) || (idx == B_MOTOR)) ? (bit(X_AXIS) | bit(Y_AXIS)) : bit(idx);
}
static void corexy_limits_set_target_pos (uint_fast8_t idx) // fn name?
{
int32_t axis_position;
switch(idx) {
case X_AXIS:
axis_position = corexy_convert_to_b_motor_steps(sys.position);
sys.position[A_MOTOR] = axis_position;
sys.position[B_MOTOR] = -axis_position;
break;
case Y_AXIS:
sys.position[A_MOTOR] = sys.position[B_MOTOR] = corexy_convert_to_a_motor_steps(sys.position);
break;
default:
sys.position[idx] = 0;
break;
}
}
// Set machine positions for homed limit switches. Don't update non-homed axes.
// NOTE: settings.max_travel[] is stored as a negative value.
static void corexy_limits_set_machine_positions (axes_signals_t cycle)
{
uint_fast8_t idx = N_AXIS;
if(settings.homing.flags.force_set_origin) {
if (cycle.mask & bit(--idx)) do {
switch(--idx) {
case X_AXIS:
sys.position[A_MOTOR] = corexy_convert_to_b_motor_steps(sys.position);
sys.position[B_MOTOR] = - sys.position[A_MOTOR];
break;
case Y_AXIS:
sys.position[A_MOTOR] = corexy_convert_to_a_motor_steps(sys.position);
sys.position[B_MOTOR] = sys.position[A_MOTOR];
break;
default:
sys.position[idx] = 0;
break;
}
} while (idx);
} else do {
if (cycle.mask & bit(--idx)) {
int32_t off_axis_position;
int32_t set_axis_position = bit_istrue(settings.homing.dir_mask.value, bit(idx))
? lroundf((settings.axis[idx].max_travel + settings.homing.pulloff) * settings.axis[idx].steps_per_mm)
: lroundf(-settings.homing.pulloff * settings.axis[idx].steps_per_mm);
switch(idx) {
case X_AXIS:
off_axis_position = corexy_convert_to_b_motor_steps(sys.position);
sys.position[A_MOTOR] = set_axis_position + off_axis_position;
sys.position[B_MOTOR] = set_axis_position - off_axis_position;
break;
case Y_AXIS:
off_axis_position = corexy_convert_to_a_motor_steps(sys.position);
sys.position[A_MOTOR] = off_axis_position + set_axis_position;
sys.position[B_MOTOR] = off_axis_position - set_axis_position;
break;
default:
sys.position[idx] = set_axis_position;
break;
}
}
} while(idx);
}
// Initialize API pointers for CoreXY kinematics
void corexy_init (void)
{
kinematics.limits_set_target_pos = corexy_limits_set_target_pos;
kinematics.limits_get_axis_mask = corexy_limits_get_axis_mask;
kinematics.limits_set_machine_positions = corexy_limits_set_machine_positions;
kinematics.plan_target_to_steps = corexy_target_to_steps;
kinematics.convert_array_steps_to_mpos = corexy_convert_array_steps_to_mpos;
}
#endif
+29
View File
@@ -0,0 +1,29 @@
/*
corexy.c - corexy kinematics implementation
Part of grblHAL
Copyright (c) 2019 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _COREXY_H_
#define _COREXY_H_
// Initialize HAL pointers for CoreXY kinematics
void corexy_init (void);
#endif
+42
View File
@@ -0,0 +1,42 @@
/*
crossbar.h - signal crossbar definitions
Not used by the core.
Part of grblHAL
Copyright (c) 2021 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _CROSSBAR_H_
#define _CROSSBAR_H_
typedef bool (*xbar_get_value_ptr)(void);
typedef void (*xbar_set_value_ptr)(bool on);
typedef void (*xbar_event_ptr)(bool on);
typedef void (*xbar_config_ptr)(void *cfg_data);
typedef struct {
uint32_t function;
void *port;
uint8_t bit;
xbar_config_ptr config;
xbar_get_value_ptr get_value;
xbar_set_value_ptr set_value;
xbar_event_ptr on_event;
} xbar_t;
#endif
+599
View File
File diff suppressed because it is too large Load Diff
+167
View File
@@ -0,0 +1,167 @@
/*
errors.h -
Part of grblHAL
Copyright (c) 2017-2021 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _ERRORS_H_
#define _ERRORS_H_
#include <stddef.h>
// Define Grbl status codes. Valid values (0-255)
typedef enum {
Status_OK = 0,
Status_ExpectedCommandLetter = 1,
Status_BadNumberFormat = 2,
Status_InvalidStatement = 3,
Status_NegativeValue = 4,
Status_HomingDisabled = 5,
Status_SettingStepPulseMin = 6,
Status_SettingReadFail = 7,
Status_IdleError = 8,
Status_SystemGClock = 9,
Status_SoftLimitError = 10,
Status_Overflow = 11,
Status_MaxStepRateExceeded = 12,
Status_CheckDoor = 13,
Status_LineLengthExceeded = 14,
Status_TravelExceeded = 15,
Status_InvalidJogCommand = 16,
Status_SettingDisabledLaser = 17,
Status_Reset = 18,
Status_NonPositiveValue = 19,
Status_GcodeUnsupportedCommand = 20,
Status_GcodeModalGroupViolation = 21,
Status_GcodeUndefinedFeedRate = 22,
Status_GcodeCommandValueNotInteger = 23,
Status_GcodeAxisCommandConflict = 24,
Status_GcodeWordRepeated = 25,
Status_GcodeNoAxisWords = 26,
Status_GcodeInvalidLineNumber = 27,
Status_GcodeValueWordMissing = 28,
Status_GcodeUnsupportedCoordSys = 29,
Status_GcodeG53InvalidMotionMode = 30,
Status_GcodeAxisWordsExist = 31,
Status_GcodeNoAxisWordsInPlane = 32,
Status_GcodeInvalidTarget = 33,
Status_GcodeArcRadiusError = 34,
Status_GcodeNoOffsetsInPlane = 35,
Status_GcodeUnusedWords = 36,
Status_GcodeG43DynamicAxisError = 37,
Status_GcodeIllegalToolTableEntry = 38,
Status_GcodeValueOutOfRange = 39,
Status_GcodeToolChangePending = 40,
Status_GcodeSpindleNotRunning = 41,
Status_GcodeIllegalPlane = 42,
Status_GcodeMaxFeedRateExceeded = 43,
Status_GcodeRPMOutOfRange = 44,
Status_LimitsEngaged = 45,
Status_HomingRequired = 46,
Status_GCodeToolError = 47,
Status_ValueWordConflict = 48,
Status_SelfTestFailed = 49,
Status_EStop = 50,
Status_MotorFault = 51,
Status_SettingValueOutOfRange = 52,
Status_SettingDisabled = 53,
// Some error codes as defined in bdring's ESP32 port
Status_SDMountError = 60,
Status_SDReadError = 61,
Status_SDFailedOpenDir = 62,
Status_SDDirNotFound = 63,
Status_SDFileEmpty = 64,
Status_BTInitError = 70,
Status_Unhandled // For internal use only
} status_code_t;
typedef struct {
status_code_t id;
const char *name;
const char *description;
} status_detail_t;
PROGMEM static const status_detail_t status_detail[] = {
{ Status_OK, "ok", NULL },
{ Status_ExpectedCommandLetter, "Expected command letter", "G-code words consist of a letter and a value. Letter was not found." },
{ Status_BadNumberFormat, "Bad number format", "Missing the expected G-code word value or numeric value format is not valid." },
{ Status_InvalidStatement, "Invalid statement", "Grbl '$' system command was not recognized or supported." },
{ Status_NegativeValue, "Value < 0", "Negative value received for an expected positive value." },
{ Status_HomingDisabled, "Homing disabled", "Homing cycle failure. Homing is not configured via settings." },
{ Status_SettingStepPulseMin, "Value < 2 microseconds", "Step pulse time must be greater or equal to 2 microseconds." },
{ Status_SettingReadFail, "EEPROM read fail. Using defaults", "An EEPROM read failed. Auto-restoring affected EEPROM to default values." },
{ Status_IdleError, "Not idle", "Grbl '$' command cannot be used unless Grbl is IDLE. Ensures smooth operation during a job." },
{ Status_SystemGClock, "G-code lock", "G-code commands are locked out during alarm or jog state." },
{ Status_SoftLimitError, "Homing not enabled", "Soft limits cannot be enabled without homing also enabled." },
{ Status_Overflow, "Line overflow", "Max characters per line exceeded. Received command line was not executed." },
{ Status_MaxStepRateExceeded, "Step rate > 30kHz", "Grbl '$' setting value cause the step rate to exceed the maximum supported." },
{ Status_CheckDoor, "Check Door", "Safety door detected as opened and door state initiated." },
{ Status_LineLengthExceeded, "Line length exceeded", "Build info or startup line exceeded EEPROM line length limit. Line not stored." },
{ Status_TravelExceeded, "Travel exceeded", "Jog target exceeds machine travel. Jog command has been ignored." },
{ Status_InvalidJogCommand, "Invalid jog command", "Jog command has no '=' or contains prohibited g-code." },
{ Status_SettingDisabledLaser, "Setting disabled", "Laser mode requires PWM output." },
{ Status_Reset, "Reset asserted", "" },
{ Status_NonPositiveValue, "Non positive value", "" },
{ Status_GcodeUnsupportedCommand, "Unsupported command", "Unsupported or invalid g-code command found in block." },
{ Status_GcodeModalGroupViolation, "Modal group violation", "More than one g-code command from same modal group found in block." },
{ Status_GcodeUndefinedFeedRate, "Undefined feed rate", "Feed rate has not yet been set or is undefined." },
{ Status_GcodeCommandValueNotInteger, "Invalid gcode ID:23", "G-code command in block requires an integer value." },
{ Status_GcodeAxisCommandConflict, "Invalid gcode ID:24", "More than one g-code command that requires axis words found in block." },
{ Status_GcodeWordRepeated, "Invalid gcode ID:25", "Repeated g-code word found in block." },
{ Status_GcodeNoAxisWords, "Invalid gcode ID:26", "No axis words found in block for g-code command or current modal state which requires them." },
{ Status_GcodeInvalidLineNumber, "Invalid gcode ID:27", "Line number value is invalid." },
{ Status_GcodeValueWordMissing, "Invalid gcode ID:28", "G-code command is missing a required value word." },
{ Status_GcodeUnsupportedCoordSys, "Invalid gcode ID:29", "G59.x work coordinate systems are not supported." },
{ Status_GcodeG53InvalidMotionMode, "Invalid gcode ID:30", "G53 only allowed with G0 and G1 motion modes." },
{ Status_GcodeAxisWordsExist, "Invalid gcode ID:31", "Axis words found in block when no command or current modal state uses them." },
{ Status_GcodeNoAxisWordsInPlane, "Invalid gcode ID:32", "G2 and G3 arcs require at least one in-plane axis word." },
{ Status_GcodeInvalidTarget, "Invalid gcode ID:33", "Motion command target is invalid." },
{ Status_GcodeArcRadiusError, "Invalid gcode ID:34", "Arc radius value is invalid." },
{ Status_GcodeNoOffsetsInPlane, "Invalid gcode ID:35", "G2 and G3 arcs require at least one in-plane offset word." },
{ Status_GcodeUnusedWords, "Invalid gcode ID:36", "Unused value words found in block." },
{ Status_GcodeG43DynamicAxisError, "Invalid gcode ID:37", "G43.1 dynamic tool length offset is not assigned to configured tool length axis." },
{ Status_GcodeIllegalToolTableEntry, "Invalid gcode ID:38", "Tool number greater than max supported value or undefined tool selected." },
{ Status_GcodeValueOutOfRange, "Invalid gcode ID:39", "Value out of range." },
{ Status_GcodeToolChangePending, "Invalid gcode ID:40", "G-code command not allowed when tool change is pending." },
{ Status_GcodeSpindleNotRunning, "Invalid gcode ID:41", "Spindle not running when motion commanded in CSS or spindle sync mode." },
{ Status_GcodeIllegalPlane, "Invalid gcode ID:42", "Plane must be ZX for threading." },
{ Status_GcodeMaxFeedRateExceeded, "Invalid gcode ID:43", "Max. feed rate exceeded." },
{ Status_GcodeRPMOutOfRange, "Invalid gcode ID:44", "RPM out of range." },
{ Status_LimitsEngaged, "Limit switch engaged", "Only homing is allowed when a limit switch is engaged." },
{ Status_HomingRequired, "Homing required", "Home machine to continue." },
{ Status_GCodeToolError, "Invalid gcode ID:47", "ATC: current tool is not set. Set current tool with M61." },
{ Status_ValueWordConflict, "Invalid gcode ID:48", "Value word conflict." },
{ Status_SelfTestFailed, "Self test failed", "Power on self test failed. A hard reset is required." },
{ Status_EStop, "E-stop", "Emergency stop active." },
{ Status_MotorFault, "Motor fault", "Motor fault." },
{ Status_SettingValueOutOfRange, "Value out of range.", "Setting value is out of range." },
{ Status_SettingDisabled, "Setting disabled", "Setting is not available, possibly due to limited driver support." },
{ Status_SDMountError, "SD Card", "SD Card mount failed." },
{ Status_SDReadError, "SD Card", "SD Card file open/read failed." },
{ Status_SDFailedOpenDir, "SD Card", "SD Card directory listing failed." },
{ Status_SDDirNotFound, "SD Card", "SD Card directory not found." },
{ Status_SDFileEmpty, "SD Card", "SD Card file empty." },
{ Status_BTInitError, "Bluetooth", "Bluetooth initalisation failed." }
};
#endif
+2748
View File
File diff suppressed because it is too large Load Diff
+480
View File
@@ -0,0 +1,480 @@
/*
gcode.h - rs274/ngc parser.
Part of grblHAL
Copyright (c) 2017-2020 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _GCODE_H_
#define _GCODE_H_
#include "nuts_bolts.h"
#include "coolant_control.h"
#include "spindle_control.h"
#include "errors.h"
// Define command actions for within execution-type modal groups (motion, stopping, non-modal). Used
// internally by the parser to know which command to execute.
// NOTE: Some values are assigned specific values to make g-code state reporting and parsing
// compile a litte smaller. Although not
// ideal, just be careful with values that state 'do not alter' and check both report.c and gcode.c
// to see how they are used, if you need to alter them.
// Modal Group G0: Non-modal actions
typedef enum {
NonModal_NoAction = 0, // (Default: Must be zero)
NonModal_Dwell = 4, // G4 (Do not alter value)
NonModal_SetCoordinateData = 10, // G10 (Do not alter value)
NonModal_GoHome_0 = 28, // G28 (Do not alter value)
NonModal_SetHome_0 = 38, // G28.1 (Do not alter value)
NonModal_GoHome_1 = 30, // G30 (Do not alter value)
NonModal_SetHome_1 = 40, // G30.1 (Do not alter value)
NonModal_AbsoluteOverride = 53, // G53 (Do not alter value)
NonModal_SetCoordinateOffset = 92, // G92 (Do not alter value)
NonModal_ResetCoordinateOffset = 102, // G92.1 (Do not alter value)
NonModal_ClearCoordinateOffset = 112, // G92.2 (Do not alter value)
NonModal_RestoreCoordinateOffset = 122 // G92.3 (Do not alter value)
} non_modal_t;
// Modal Group G1: Motion modes
typedef enum {
MotionMode_Seek = 0, // G0 (Default: Must be zero)
MotionMode_Linear = 1, // G1 (Do not alter value)
MotionMode_CwArc = 2, // G2 (Do not alter value)
MotionMode_CcwArc = 3, // G3 (Do not alter value)
MotionMode_CubicSpline = 5, // G5 (Do not alter value)
MotionMode_SpindleSynchronized = 33, // G33 (Do not alter value)
MotionMode_DrillChipBreak = 73, // G73 (Do not alter value)
MotionMode_Threading = 76, // G76 (Do not alter value)
MotionMode_CannedCycle81 = 81, // G81 (Do not alter value)
MotionMode_CannedCycle82 = 82, // G82 (Do not alter value)
MotionMode_CannedCycle83 = 83, // G83 (Do not alter value)
MotionMode_CannedCycle85 = 85, // G85 (Do not alter value)
MotionMode_CannedCycle86 = 86, // G86 (Do not alter value)
MotionMode_CannedCycle89 = 89, // G89 (Do not alter value)
MotionMode_ProbeToward = 140, // G38.2 (Do not alter value)
MotionMode_ProbeTowardNoError = 141, // G38.3 (Do not alter value)
MotionMode_ProbeAway = 142, // G38.4 (Do not alter value)
MotionMode_ProbeAwayNoError = 143, // G38.5 (Do not alter value)
MotionMode_None = 80 // G80 (Do not alter value)
} motion_mode_t;
// Modal Group G2: Plane select
typedef enum {
PlaneSelect_XY = 0, // G17 (Default: Must be zero)
PlaneSelect_ZX = 1, // G18 (Do not alter value)
PlaneSelect_YZ = 2 // G19 (Do not alter value)
} plane_select_t;
// Modal Group G4: Arc IJK distance mode
//#define DISTANCE_ARC_MODE_INCREMENTAL 0 // G91.1 (Default: Must be zero)
// Modal Group M4: Program flow
typedef enum {
ProgramFlow_Running = 0, // (Default: Must be zero)
ProgramFlow_Paused = 3, // M0
ProgramFlow_OptionalStop = 1, // M1
ProgramFlow_CompletedM2 = 2, // M2 (Do not alter value)
ProgramFlow_CompletedM30 = 30, // M30 (Do not alter value)
ProgramFlow_CompletedM60 = 60 // M60 (Do not alter value)
} program_flow_t;
// Modal Group G5: Feed rate mode
typedef enum {
FeedMode_UnitsPerMin = 0, // G94 (Default: Must be zero)
FeedMode_InverseTime = 1, // G93 (Do not alter value)
FeedMode_UnitsPerRev = 2 // G95 (Do not alter value)
} feed_mode_t;
// Modal Group G10: Canned cycle return mode
typedef enum {
CCRetractMode_Previous = 0, // G98 (Default: Must be zero)
CCRetractMode_RPos = 1 // G99 (Do not alter value)
} cc_retract_mode_t;
// Modal Group G7: Cutter radius compensation mode
//#define CUTTER_COMP_DISABLE 0 // G40 (Default: Must be zero)
// Modal Group G13: Control mode
//#define CONTROL_MODE_EXACT_PATH 0 // G61 (Default: Must be zero)
// Modal Group G8: Tool length offset
typedef enum {
ToolLengthOffset_Cancel = 0, // G49 (Default: Must be zero)
ToolLengthOffset_Enable = 1, // G43
ToolLengthOffset_EnableDynamic = 2, // G43.1
ToolLengthOffset_ApplyAdditional = 3 // G43.2
} tool_offset_mode_t;
// Modal Group M9: Override control
typedef enum {
Override_Parking = 56, // M56
Override_FeedHold = 53, // M53
Override_FeedSpeed = 49, // M49
Override_FeedRate = 50, // M50
Override_SpindleSpeed = 51 // M51
} override_mode_t;
// Modal Group G12: Active work coordinate system
// N/A: Stores coordinate system value (54-59) to change to.
// Modal Group G14: Spindle Speed Mode
typedef enum {
SpindleSpeedMode_RPM = 0, // G96 (Default: Must be zero)
SpindleSpeedMode_CSS = 1 // G97 (Do not alter value)
} spindle_rpm_mode_t;
typedef struct output_command {
bool is_digital;
bool is_executed;
uint8_t port;
int32_t value;
struct output_command *next;
} output_command_t;
typedef enum {
WaitMode_Immediate = 0,
WaitMode_Rise,
WaitMode_Fall,
WaitMode_High,
WaitMode_Low,
WaitMode_Max // Used for validation only
} wait_mode_t;
// Modal Group M10: User defined M commands
// NOTE: Not used by core, may be used by driver code
typedef enum {
UserMCode_Ignore = 0,
UserMCode_Generic0 = 100,
UserMCode_Generic1 = 101,
UserMCode_Generic2 = 102,
UserMCode_Generic3 = 103,
UserMCode_Generic4 = 104,
LaserPPI_Enable = 112,
LaserPPI_Rate = 113,
LaserPPI_PulseLength = 114,
Laser_Coolant = 115,
Trinamic_DebugReport = 122,
Trinamic_StepperCurrent = 906,
Trinamic_ModeToggle = 569,
Trinamic_ReportPrewarnFlags = 911,
Trinamic_ClearPrewarnFlags = 912,
Trinamic_HybridThreshold = 913,
Trinamic_HomingSensitivity = 914
} user_mcode_t;
// Define g-code parser position updating flags
typedef enum {
GCUpdatePos_Target = 0,
GCUpdatePos_System,
GCUpdatePos_None
} pos_update_t;
// Define probe cycle exit states and assign proper position updating.
typedef enum {
GCProbe_Found = GCUpdatePos_System,
GCProbe_Abort = GCUpdatePos_None,
GCProbe_FailInit = GCUpdatePos_None,
GCProbe_FailEnd = GCUpdatePos_Target,
#ifdef SET_CHECK_MODE_PROBE_TO_START
GCProbe_CheckMode = GCUpdatePos_None
#else
GCProbe_CheckMode = GCUpdatePos_Target
#endif
} gc_probe_t;
// Define parser words bitfield
typedef union {
uint32_t mask;
uint32_t value;
struct {
uint32_t e :1,
f :1,
h :1,
i :1,
j :1,
k :1,
l :1,
n :1,
p :1,
r :1,
s :1,
t :1,
x :1,
y :1,
z :1,
q :1,
#if N_AXIS > 3
a :1,
b :1,
c :1,
#endif
d :1;
};
} parameter_words_t;
// Define gcode parser flags for handling special cases.
typedef union {
uint16_t value;
struct {
uint16_t jog_motion :1,
canned_cycle_change :1, // Use motion_mode_changed?
arc_is_clockwise :1,
probe_is_away :1,
probe_is_no_error :1,
spindle_force_sync :1,
laser_disable :1,
laser_is_motion :1,
set_coolant :1,
motion_mode_changed :1,
reserved :6;
};
} gc_parser_flags_t;
typedef union {
uint8_t value;
struct {
uint8_t feed_rate_disable :1,
feed_hold_disable :1,
spindle_rpm_disable :1,
parking_disable :1,
reserved :3,
sync :1;
};
} gc_override_flags_t;
typedef union {
float values[N_AXIS];
struct {
float x;
float y;
float z;
#ifdef A_AXIS
float a;
#endif
#ifdef B_AXIS
float b;
#endif
#ifdef C_AXIS
float c;
#endif
};
} coord_data_t;
typedef enum {
CoordinateSystem_G54 = 0,
CoordinateSystem_G55,
CoordinateSystem_G56,
CoordinateSystem_G57,
CoordinateSystem_G58,
CoordinateSystem_G59,
#if COMPATIBILITY_LEVEL <= 1
CoordinateSystem_G59_1,
CoordinateSystem_G59_2,
CoordinateSystem_G59_3,
#endif
N_WorkCoordinateSystems,
CoordinateSystem_G28 = N_WorkCoordinateSystems,
CoordinateSystem_G30,
CoordinateSystem_G92,
N_CoordinateSystems
} coord_system_id_t;
typedef struct {
float xyz[N_AXIS];
coord_system_id_t id;
} coord_system_t;
typedef struct {
uint8_t axis_0;
uint8_t axis_1;
uint8_t axis_linear;
} plane_t;
// NOTE: When this struct is zeroed, the above defines set the defaults for the system.
typedef struct {
motion_mode_t motion; // {G0,G1,G2,G3,G38.2,G80}
feed_mode_t feed_mode; // {G93,G94}
bool units_imperial; // {G20,G21}
bool distance_incremental; // {G90,G91}
bool diameter_mode; // {G7,G8} Lathe diameter mode.
// uint8_t distance_arc; // {G91.1} NOTE: Don't track. Only default supported.
plane_select_t plane_select; // {G17,G18,G19}
// uint8_t cutter_comp; // {G40} NOTE: Don't track. Only default supported.
tool_offset_mode_t tool_offset_mode; // {G43,G43.1,G49}
coord_system_t coord_system; // {G54,G55,G56,G57,G58,G59,G59.1,G59.2,G59.3}
// uint8_t control; // {G61} NOTE: Don't track. Only default supported.
program_flow_t program_flow; // {M0,M1,M2,M30,M60}
coolant_state_t coolant; // {M7,M8,M9}
spindle_state_t spindle; // {M3,M4,M5}
gc_override_flags_t override_ctrl; // {M48,M49,M50,M51,M53,M56}
spindle_rpm_mode_t spindle_rpm_mode; // {G96,G97}
cc_retract_mode_t retract_mode; // {G98,G99}
bool scaling_active; // {G50,G51}
bool canned_cycle_active;
float spline_pq[2]; // {G5}
} gc_modal_t;
typedef struct {
float d; // Max spindle RPM in Constant Surface Speed Mode (G96)
float e; // Thread taper length (G76)
float f; // Feed
float ijk[3]; // I,J,K Axis arc offsets
float k; // G33 distance per revolution
float p; // G10 or dwell parameters
float q; // User defined M-code parameter (G82 peck drilling, not supported)
float r; // Arc radius or retract position
float s; // Spindle speed
float xyz[N_AXIS]; // X,Y,Z Translational axes
coord_system_t coord_data; // Coordinate data
int32_t n; // Line number
uint32_t h; // Tool number
uint32_t t; // Tool selection
uint8_t l; // G10 or canned cycles parameters
} gc_values_t;
typedef struct {
float xyz[3];
float delta;
float dwell;
float prev_position;
float retract_position; // Canned cycle retract position
bool rapid_retract;
bool spindle_off;
cc_retract_mode_t retract_mode;
bool change;
} gc_canned_t;
typedef enum {
Taper_None = 0,
Taper_Entry,
Taper_Exit,
Taper_Both
} gc_taper_type;
typedef struct {
float pitch;
float z_final;
float peak;
float initial_depth;
float depth;
float depth_degression;
float main_taper_height;
float end_taper_length;
float infeed_angle;
float cut_direction;
uint_fast16_t spring_passes;
gc_taper_type end_taper_type;
} gc_thread_data;
typedef struct {
float offset[N_AXIS];
float radius;
uint32_t tool;
} tool_data_t;
// Data used for Constant Surface Speed Mode calculations
typedef struct {
float surface_speed; // Surface speed in millimeters/min
float target_rpm; // Target RPM at end of movement
float max_rpm; // Maximum spindle RPM
float tool_offset; // Tool offset
uint_fast8_t axis; // Linear (tool) axis
bool active;
} css_data_t;
typedef struct {
float rpm; // RPM
css_data_t css; // Data used for Constant Surface Speed Mode calculations
} spindle_t;
typedef struct {
gc_modal_t modal;
gc_canned_t canned;
spindle_t spindle; // RPM
float feed_rate; // Millimeters/min
float distance_per_rev; // Millimeters/rev
float position[N_AXIS]; // Where the interpreter considers the tool to be at this point in the code
int32_t line_number; // Last line number sent
uint32_t tool_pending; // Tool to be selected on next M6
bool file_run; // Tracks % command
bool is_laser_ppi_mode;
bool is_rpm_rate_adjusted;
bool tool_change;
status_code_t last_error; // last return value from parser
// The following variables are not cleared upon warm restart when COMPATIBILITY_LEVEL <= 1
float g92_coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to
// machine zero in mm. Persistent and loaded from non-volatile storage
// on boot when COMPATIBILITY_LEVEL <= 1
float tool_length_offset[N_AXIS]; // Tracks tool length offset when enabled
tool_data_t *tool; // Tracks tool number and tool offset
} parser_state_t;
typedef struct {
float xyz[N_AXIS]; // Center point
float ijk[N_AXIS]; // Scaling factors
} scale_factor_t;
extern parser_state_t gc_state;
#ifdef N_TOOLS
extern tool_data_t tool_table[N_TOOLS + 1];
#else
extern tool_data_t tool_table;
#endif
typedef struct {
non_modal_t non_modal_command;
override_mode_t override_command; // TODO: add to non_modal above?
user_mcode_t user_mcode;
bool user_mcode_sync;
gc_modal_t modal;
gc_values_t values;
output_command_t output_command;
} parser_block_t;
// Initialize the parser
void gc_init (void);
// Execute one block of rs275/ngc/g-code
status_code_t gc_execute_block (char *block, char *message);
// Sets g-code parser position in mm. Input in steps. Called by the system abort and hard
// limit pull-off routines.
#define gc_sync_position() system_convert_array_steps_to_mpos (gc_state.position, sys.position)
// Sets g-code parser and planner position in mm.
#define sync_position() plan_sync_position(); system_convert_array_steps_to_mpos (gc_state.position, sys.position)
// Set dynamic laser power mode to PPI (Pulses Per Inch)
// Driver support for pulsing the laser on signal is required for this to work.
// Returns true if driver uses hardware implementation.
bool gc_laser_ppi_enable (uint_fast16_t ppi, uint_fast16_t pulse_length);
// Gets axes scaling state.
axes_signals_t gc_get_g51_state (void);
float *gc_get_scaling (void);
// Get current axis offset.
float gc_get_offset (uint_fast8_t idx);
void gc_set_tool_offset (tool_offset_mode_t mode, uint_fast8_t idx, int32_t offset);
plane_t *gc_get_plane_data (plane_t *plane, plane_select_t select);
#endif
+276
View File
@@ -0,0 +1,276 @@
/*
grbl.h - main Grbl include file for compile time configuration
Part of grblHAL
Copyright (c) 2017-2021 Terje Io
Copyright (c) 2015-2016 Sungeun K. Jeon for Gnea Research LLC
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _GRBL_H_
#define _GRBL_H_
#include <stdint.h>
#include <stdbool.h>
#include "config.h"
// Grbl versioning system
#if COMPATIBILITY_LEVEL == 0
#define GRBL_VERSION "1.1f"
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_VERSION_BUILD "20210222"
// The following symbols are set here if not already set by the compiler or in config.h
// Do NOT change here!
#ifdef GRBL_ESP32
#include "esp_attr.h"
#define ISR_CODE IRAM_ATTR
#else
// Used to decorate code run in interrupt context.
// Do not remove or change unless you know what you are doing.
#define ISR_CODE
#endif
#ifdef ARDUINO
#include <Arduino.h>
#endif
#ifndef PROGMEM
#define PROGMEM
#endif
#ifndef N_AXIS
#define N_AXIS 3 // Number of axes
#endif
#ifndef COMPATIBILITY_LEVEL
#define COMPATIBILITY_LEVEL 0
#endif
#if (defined(COREXY) || defined(WALL_PLOTTER) || defined(MASLOW_ROUTER)) && !defined(KINEMATICS_API)
#define KINEMATICS_API
#endif
#ifndef CHECK_MODE_DELAY
#define CHECK_MODE_DELAY 0 // ms
#endif
#ifndef SAFETY_DOOR_SPINDLE_DELAY
#define SAFETY_DOOR_SPINDLE_DELAY 4.0f // Float (seconds)
#endif
#ifndef SAFETY_DOOR_COOLANT_DELAY
#define SAFETY_DOOR_COOLANT_DELAY 1.0f // Float (seconds)
#endif
#ifndef SPINDLE_RPM_CONTROLLED
#define SPINDLE_PWM_DIRECT
#endif
#ifndef SLEEP_DURATION
#define SLEEP_DURATION 5.0f // Number of minutes before sleep mode is entered.
#endif
#ifndef BUFFER_NVSDATA_DISABLE
#define BUFFER_NVSDATA
#endif
// The following symbols are default values that are unlikely to be changed
// Do not change unless you know what you are doing!
// Define realtime command special characters. These characters are 'picked-off' directly from the
// serial read data stream and are not passed to the grbl line execution parser. Select characters
// that do not and must not exist in the streamed g-code program. ASCII control characters may be
// used, if they are available per user setup. Also, extended ASCII codes (>127), which are never in
// g-code programs, maybe selected for interface programs.
// NOTE: If changed, manually update help message in report.c.
#define CMD_EXIT 0x03 // ctrl-C (ETX)
#define CMD_REBOOT 0x14 // ctrl-T (DC4) - only acted upon if preceeded by 0x1B (ESC)
#define CMD_RESET 0x18 // ctrl-X (CAN)
#define CMD_STOP 0x19 // ctrl-Y (EM)
#define CMD_STATUS_REPORT_LEGACY '?'
#define CMD_CYCLE_START_LEGACY '~'
#define CMD_FEED_HOLD_LEGACY '!'
#define CMD_PROGRAM_DEMARCATION '%'
// NOTE: All override realtime commands must be in the extended ASCII character set, starting
// at character value 128 (0x80) and up to 255 (0xFF). If the normal set of realtime commands,
// such as status reports, feed hold, reset, and cycle start, are moved to the extended set
// space, protocol.c's protocol_process_realtime() will need to be modified to accomodate the change.
#define CMD_STATUS_REPORT 0x80 // TODO: use 0x05 ctrl-E ENQ instead?
#define CMD_CYCLE_START 0x81 // TODO: use 0x06 ctrl-F ACK instead? or SYN/DC2/DC3?
#define CMD_FEED_HOLD 0x82 // TODO: use 0x15 ctrl-U NAK instead?
#define CMD_GCODE_REPORT 0x83
#define CMD_SAFETY_DOOR 0x84
#define CMD_JOG_CANCEL 0x85
//#define CMD_DEBUG_REPORT 0x86 // Only when DEBUG enabled, sends debug report in '{}' braces.
#define CMD_STATUS_REPORT_ALL 0x87
#define CMD_OPTIONAL_STOP_TOGGLE 0x88
#define CMD_OVERRIDE_FEED_RESET 0x90 // Restores feed override value to 100%.
#define CMD_OVERRIDE_FEED_COARSE_PLUS 0x91
#define CMD_OVERRIDE_FEED_COARSE_MINUS 0x92
#define CMD_OVERRIDE_FEED_FINE_PLUS 0x93
#define CMD_OVERRIDE_FEED_FINE_MINUS 0x94
#define CMD_OVERRIDE_RAPID_RESET 0x95 // Restores rapid override value to 100%.
#define CMD_OVERRIDE_RAPID_MEDIUM 0x96
#define CMD_OVERRIDE_RAPID_LOW 0x97
// #define CMD_OVERRIDE_RAPID_EXTRA_LOW 0x98 // *NOT SUPPORTED*
#define CMD_OVERRIDE_SPINDLE_RESET 0x99 // Restores spindle override value to 100%.
#define CMD_OVERRIDE_SPINDLE_COARSE_PLUS 0x9A
#define CMD_OVERRIDE_SPINDLE_COARSE_MINUS 0x9B
#define CMD_OVERRIDE_SPINDLE_FINE_PLUS 0x9C
#define CMD_OVERRIDE_SPINDLE_FINE_MINUS 0x9D
#define CMD_OVERRIDE_SPINDLE_STOP 0x9E
#define CMD_OVERRIDE_COOLANT_FLOOD_TOGGLE 0xA0
#define CMD_OVERRIDE_COOLANT_MIST_TOGGLE 0xA1
#define CMD_PID_REPORT 0xA2
#define CMD_TOOL_ACK 0xA3
#define CMD_PROBE_CONNECTED_TOGGLE 0xA4
// System motion line numbers must be zero.
#define JOG_LINE_NUMBER 0
// Number of blocks Grbl executes upon startup. These blocks are stored in non-volatile storage, where the size
// and addresses are defined in settings.h. With the current settings, up to 2 startup blocks may
// be stored and executed in order. These startup blocks would typically be used to set the g-code
// parser state depending on user preferences.
#define N_STARTUP_LINE 2 // Integer (1-2)
// Number of decimal places (scale) output by Grbl for certain value types. These settings
// are determined by realistic and commonly observed values in CNC machines. For example, position
// values cannot be less than 0.001mm or 0.0001in, because machines can not be physically more
// precise this. So, there is likely no need to change these, but you can if you need to here.
// NOTE: Must be an integer value from 0 to ~4. More than 4 may exhibit round-off errors.
#define N_DECIMAL_COORDVALUE_INCH 4 // Coordinate or position value in inches
#define N_DECIMAL_COORDVALUE_MM 3 // Coordinate or position value in mm
#define N_DECIMAL_RATEVALUE_INCH 1 // Rate or velocity value in in/min
#define N_DECIMAL_RATEVALUE_MM 0 // Rate or velocity value in mm/min
#define N_DECIMAL_SETTINGVALUE 3 // Floating point setting values
#define N_DECIMAL_RPMVALUE 0 // RPM value in rotations per min
#define N_DECIMAL_PIDVALUE 3 // PID value
// ---------------------------------------------------------------------------------------
// ADVANCED CONFIGURATION OPTIONS:
// Enables code for debugging purposes. Not for general use and always in constant flux.
// #define DEBUG // Uncomment to enable. Default disabled.
// Configure rapid, feed, and spindle override settings. These values define the max and min
// allowable override values and the coarse and fine increments per command received. Please
// note the allowable values in the descriptions following each define.
#define DEFAULT_FEED_OVERRIDE 100 // 100%. Don't change this value.
#define MAX_FEED_RATE_OVERRIDE 200 // Percent of programmed feed rate (100-255). Usually 120% or 200%
#define MIN_FEED_RATE_OVERRIDE 10 // Percent of programmed feed rate (1-100). Usually 50% or 1%
#define FEED_OVERRIDE_COARSE_INCREMENT 10 // (1-99). Usually 10%.
#define FEED_OVERRIDE_FINE_INCREMENT 1 // (1-99). Usually 1%.
#define DEFAULT_RAPID_OVERRIDE 100 // 100%. Don't change this value.
#define RAPID_OVERRIDE_MEDIUM 50 // Percent of rapid (1-99). Usually 50%.
#define RAPID_OVERRIDE_LOW 25 // Percent of rapid (1-99). Usually 25%.
// #define RAPID_OVERRIDE_EXTRA_LOW 5 // *NOT SUPPORTED* Percent of rapid (1-99). Usually 5%.
// #define ENABLE_SPINDLE_LINEARIZATION // Uncomment to enable spindle RPM linearization. Requires compatible driver if enabled.
#define SPINDLE_NPWM_PIECES 4 // Maximum number of pieces for spindle RPM linearization, do not change unless more are needed.
#define DEFAULT_SPINDLE_RPM_OVERRIDE 100 // 100%. Don't change this value.
#define MAX_SPINDLE_RPM_OVERRIDE 200 // Percent of programmed spindle speed (100-255). Usually 200%.
#define MIN_SPINDLE_RPM_OVERRIDE 10 // Percent of programmed spindle speed (1-100). Usually 10%.
#define SPINDLE_OVERRIDE_COARSE_INCREMENT 10 // (1-99). Usually 10%.
#define SPINDLE_OVERRIDE_FINE_INCREMENT 1 // (1-99). Usually 1%.
// Some status report data isn't necessary for realtime, only intermittently, because the values don't
// change often. The following macros configures how many times a status report needs to be called before
// the associated data is refreshed and included in the status report. However, if one of these value
// changes, Grbl will automatically include this data in the next status report, regardless of what the
// count is at the time. This helps reduce the communication overhead involved with high frequency reporting
// and agressive streaming. There is also a busy and an idle refresh count, which sets up Grbl to send
// refreshes more often when its not doing anything important. With a good GUI, this data doesn't need
// to be refreshed very often, on the order of a several seconds.
// NOTE: WCO refresh must be 2 or greater. OVERRIDE refresh must be 1 or greater.
//#define REPORT_OVERRIDE_REFRESH_BUSY_COUNT 20 // (1-255)
//#define REPORT_OVERRIDE_REFRESH_IDLE_COUNT 10 // (1-255) Must be less than or equal to the busy count
//#define REPORT_WCO_REFRESH_BUSY_COUNT 30 // (2-255)
//#define REPORT_WCO_REFRESH_IDLE_COUNT 10 // (2-255) Must be less than or equal to the busy count
// The temporal resolution of the acceleration management subsystem. A higher number gives smoother
// acceleration, particularly noticeable on machines that run at very high feedrates, but may negatively
// impact performance. The correct value for this parameter is machine dependent, so it's advised to
// set this only as high as needed. Approximate successful values can widely range from 50 to 200 or more.
// NOTE: Changing this value also changes the execution time of a segment in the step segment buffer.
// When increasing this value, this stores less overall time in the segment buffer and vice versa. Make
// certain the step segment buffer is increased/decreased to account for these changes.
//#define ACCELERATION_TICKS_PER_SECOND 100
// Adaptive Multi-Axis Step Smoothing (AMASS) is an advanced feature that does what its name implies,
// smoothing the stepping of multi-axis motions. This feature smooths motion particularly at low step
// frequencies below 10kHz, where the aliasing between axes of multi-axis motions can cause audible
// noise and shake your machine. At even lower step frequencies, AMASS adapts and provides even better
// step smoothing. See stepper.c for more details on the AMASS system works.
#define ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING // Default enabled. Comment to disable.
// Define Adaptive Multi-Axis Step-Smoothing(AMASS) levels and cutoff frequencies. The highest level
// frequency bin starts at 0Hz and ends at its cutoff frequency. The next lower level frequency bin
// starts at the next higher cutoff frequency, and so on. The cutoff frequencies for each level must
// be considered carefully against how much it over-drives the stepper ISR, the accuracy of the 16-bit
// timer, and the CPU overhead. Level 0 (no AMASS, normal operation) frequency bin starts at the
// Level 1 cutoff frequency and up to as fast as the CPU allows (over 30kHz in limited testing).
// NOTE: AMASS cutoff frequency multiplied by ISR overdrive factor must not exceed maximum step frequency.
// NOTE: Current settings are set to overdrive the ISR to no more than 16kHz, balancing CPU overhead
// and timer accuracy. Do not alter these settings unless you know what you are doing.
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
#ifndef MAX_AMASS_LEVEL
#define MAX_AMASS_LEVEL 3
#endif
#if MAX_AMASS_LEVEL <= 0
error "AMASS must have 1 or more levels to operate correctly."
#endif
#endif
// Sets the maximum step rate allowed to be written as a Grbl setting. This option enables an error
// check in the settings module to prevent settings values that will exceed this limitation. The maximum
// step rate is strictly limited by the CPU speed and will change if something other than an AVR running
// at 16MHz is used.
// NOTE: For now disabled, will enable if flash space permits.
// #define MAX_STEP_RATE_HZ 30000 // Hz
// With this enabled, Grbl sends back an echo of the line it has received, which has been pre-parsed (spaces
// removed, capitalized letters, no comments) and is to be immediately executed by Grbl. Echoes will not be
// sent upon a line buffer overflow, but should for all normal lines sent to Grbl. For example, if a user
// sendss the line 'g1 x1.032 y2.45 (test comment)', Grbl will echo back in the form '[echo: G1X1.032Y2.45]'.
// NOTE: Only use this for debugging purposes!! When echoing, this takes up valuable resources and can effect
// performance. If absolutely needed for normal operation, the serial write buffer should be greatly increased
// to help minimize transmission waiting within the serial write protocol.
// #define REPORT_ECHO_LINE_RECEIVED // Default disabled. Uncomment to enable.
// Sets which axis the tool length offset is applied. Assumes the spindle is always parallel with
// the selected axis with the tool oriented toward the negative direction. In other words, a positive
// tool length offset value is subtracted from the current location.
#if COMPATIBILITY_LEVEL > 2 && defined(TOOL_LENGTH_OFFSET_AXIS) == 0
#define TOOL_LENGTH_OFFSET_AXIS Z_AXIS // Default z-axis. Valid values are X_AXIS, Y_AXIS, or Z_AXIS.
#endif
// Max length of gcode lines (blocks) stored in non-volatile storage
#if N_AXIS == 6 && COMPATIBILITY_LEVEL <= 1
#define MAX_STORED_LINE_LENGTH 60 // do not change!
#else
#define MAX_STORED_LINE_LENGTH 70 // do not set > 70 unless less than 5 axes are enabled or COMPATIBILITY_LEVEL > 1
#endif
#endif
+277
View File
@@ -0,0 +1,277 @@
/*
grbllib.c - An embedded CNC Controller with rs274/ngc (g-code) support
Part of grblHAL
Copyright (c) 2017-2021 Terje Io
Copyright (c) 2011-2015 Sungeun K. Jeon
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "hal.h"
#include "nuts_bolts.h"
#include "tool_change.h"
#include "override.h"
#include "protocol.h"
#include "limits.h"
#include "report.h"
#include "state_machine.h"
#include "nvs_buffer.h"
#ifdef ENABLE_BACKLASH_COMPENSATION
#include "motion_control.h"
#endif
#ifdef KINEMATICS_API
#include "kinematics.h"
#endif
#ifdef COREXY
#include "corexy.h"
#endif
#ifdef WALL_PLOTTER
#include "wall_plotter.h"
#endif
// Declare system global variable structure
system_t sys = {0};
grbl_t grbl;
grbl_hal_t hal;
// called from stream drivers while tx is blocking, return false to terminate
static bool stream_tx_blocking (void)
{
// TODO: Restructure st_prep_buffer() calls to be executed here during a long print.
grbl.on_execute_realtime(state_get());
return !(sys.rt_exec_state & EXEC_RESET);
}
#ifdef KINEMATICS_API
kinematics_t kinematics;
// called from mc_line() to segment lines if not overridden, default implementation for pass-through
static bool kinematics_segment_line (float *target, plan_line_data_t *pl_data, bool init)
{
static uint_fast8_t iterations;
if(init)
iterations = 2;
else
iterations--;
return iterations != 0;
}
#endif
#ifdef DEBUGOUT
static void debug_out (bool on)
{
// NOOP
}
#endif
void dummy_bool_handler (bool arg)
{
// NOOP
}
// main entry point
int grbl_enter (void)
{
#ifdef N_TOOLS
assert(NVS_ADDR_GLOBAL + sizeof(settings_t) + NVS_CRC_BYTES < NVS_ADDR_TOOL_TABLE);
#else
assert(NVS_ADDR_GLOBAL + sizeof(settings_t) + NVS_CRC_BYTES < NVS_ADDR_PARAMETERS);
#endif
assert(NVS_ADDR_PARAMETERS + N_CoordinateSystems * (sizeof(coord_data_t) + NVS_CRC_BYTES) < NVS_ADDR_STARTUP_BLOCK);
assert(NVS_ADDR_STARTUP_BLOCK + N_STARTUP_LINE * (sizeof(stored_line_t) + NVS_CRC_BYTES) < NVS_ADDR_BUILD_INFO);
bool looping = true, driver_ok;
// Clear all and set some core function pointers
memset(&grbl, 0, sizeof(grbl_t));
grbl.on_execute_realtime = protocol_execute_noop;
grbl.protocol_enqueue_gcode = protocol_enqueue_gcode;
grbl.on_report_options = dummy_bool_handler;
// Clear all and set some HAL function pointers
memset(&hal, 0, sizeof(grbl_hal_t));
hal.version = HAL_VERSION; // Update when signatures and/or contract is changed - driver_init() should fail
hal.driver_reset = dummy_handler;
hal.irq_enable = dummy_handler;
hal.irq_disable = dummy_handler;
hal.nvs.size = GRBL_NVS_SIZE;
hal.stream.enqueue_realtime_command = protocol_enqueue_realtime_command;
hal.limits.interrupt_callback = limit_interrupt_handler;
hal.control.interrupt_callback = control_interrupt_handler;
hal.stepper.interrupt_callback = stepper_driver_interrupt_handler;
hal.stream_blocking_callback = stream_tx_blocking;
hal.signals_cap.reset = hal.signals_cap.feed_hold = hal.signals_cap.cycle_start = On;
sys.cold_start = true;
#ifdef BUFFER_NVSDATA
nvs_buffer_alloc(); // Allocate memory block for NVS buffer
#endif
report_init_fns();
#ifdef KINEMATICS_API
memset(&kinematics, 0, sizeof(kinematics_t));
kinematics.segment_line = kinematics_segment_line; // default to no segmentation
#endif
#ifdef DEBUGOUT
hal.debug_out = debug_out; // must be overridden by driver to have any effect
#endif
driver_ok = driver_init();
#if COMPATIBILITY_LEVEL > 0
hal.stream.suspend_read = NULL;
#endif
#ifndef ENABLE_SAFETY_DOOR_INPUT_PIN
hal.signals_cap.safety_door_ajar = Off;
#else
driver_ok &= hal.signals_cap.safety_door_ajar;
#endif
#ifdef BUFFER_NVSDATA
nvs_buffer_init();
#endif
settings_init(); // Load Grbl settings from non-volatile storage
memset(sys.position, 0, sizeof(sys.position)); // Clear machine position.
// check and configure driver
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
driver_ok = driver_ok && hal.driver_cap.amass_level >= MAX_AMASS_LEVEL;
hal.driver_cap.amass_level = MAX_AMASS_LEVEL;
#else
hal.driver_cap.amass_level = 0;
#endif
#ifdef DEFAULT_STEP_PULSE_DELAY
driver_ok = driver_ok & hal.driver_cap.step_pulse_delay;
#endif
/*
#if AXIS_N_SETTINGS > 4
driver_ok = driver_ok & hal.driver_cap.axes >= AXIS_N_SETTINGS;
#endif
*/
sys.mpg_mode = false;
driver_ok = driver_ok && hal.driver_setup(&settings);
#ifdef ENABLE_SPINDLE_LINEARIZATION
driver_ok = driver_ok && hal.driver_cap.spindle_pwm_linearization;
#endif
#ifdef SPINDLE_PWM_DIRECT
driver_ok = driver_ok && hal.spindle.get_pwm != NULL && hal.spindle.update_pwm != NULL;
#endif
if(!driver_ok) {
hal.stream.write("grblHAL: incompatible driver" ASCII_EOL);
while(true);
}
if(hal.get_position)
hal.get_position(&sys.position); // TODO: restore on abort when returns true?
#ifdef COREXY
corexy_init();
#endif
#ifdef WALL_PLOTTER
wall_plotter_init();
#endif
sys.driver_started = true;
// "Wire" homing switches to limit switches if not provided by the driver.
if(hal.homing.get_state == NULL)
hal.homing.get_state = hal.limits.get_state;
// Grbl initialization loop upon power-up or a system abort. For the latter, all processes
// will return to this loop to be cleanly re-initialized.
while(looping) {
// Reset report entry points
report_init_fns();
if(!sys.position_lost || settings.homing.flags.keep_on_reset)
memset(&sys, 0, offsetof(system_t, homed)); // Clear system variables except alarm & homed status.
else
memset(&sys, 0, offsetof(system_t, alarm)); // Clear system variables except state & alarm.
sys.override.feed_rate = DEFAULT_FEED_OVERRIDE; // Set to 100%
sys.override.rapid_rate = DEFAULT_RAPID_OVERRIDE; // Set to 100%
sys.override.spindle_rpm = DEFAULT_SPINDLE_RPM_OVERRIDE; // Set to 100%
if(settings.parking.flags.enabled)
sys.override.control.parking_disable = settings.parking.flags.deactivate_upon_init;
flush_override_buffers();
// Reset Grbl primary systems.
hal.stream.reset_read_buffer(); // Clear input stream buffer
gc_init(); // Set g-code parser to default state
hal.limits.enable(settings.limits.flags.hard_enabled, false);
plan_reset(); // Clear block buffer and planner variables
st_reset(); // Clear stepper subsystem variables.
limits_set_homing_axes(); // Set axes to be homed from settings.
#ifdef ENABLE_BACKLASH_COMPENSATION
mc_backlash_init(); // Init backlash configuration.
#endif
// Sync cleared gcode and planner positions to current system position.
sync_position();
if(hal.stepper.disable_motors)
hal.stepper.disable_motors((axes_signals_t){0}, SquaringMode_Both);
if(!hal.driver_cap.atc)
tc_init();
// Print welcome message. Indicates an initialization has occured at power-up or with a reset.
report_init_message();
if(state_get() == STATE_ESTOP)
state_set(STATE_ALARM);
if(hal.driver_cap.mpg_mode)
hal.stream.enqueue_realtime_command(sys.mpg_mode ? CMD_STATUS_REPORT_ALL : CMD_STATUS_REPORT);
// Start Grbl main loop. Processes program inputs and executes them.
if(!(looping = protocol_main_loop()))
looping = hal.driver_release == NULL || hal.driver_release();
sys.cold_start = false;
}
return 0;
}
+39
View File
@@ -0,0 +1,39 @@
/*
grbllib.h - An embedded CNC Controller with rs274/ngc (g-code) support
Part of grblHAL
Copyright (c) 2011-2015 Sungeun K. Jeon
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _GRBLLIB_H_
#define _GRBLLIB_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
int grbl_enter (void);
#ifdef __cplusplus
}
#endif
#endif
+375
View File
@@ -0,0 +1,375 @@
/*
hal.h - HAL (Hardware Abstraction Layer) entry points structures and capabilities type
Part of grblHAL
Copyright (c) 2016-2021 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _HAL_H_
#define _HAL_H_
#include "grbl.h"
#include "gcode.h"
#include "system.h"
#include "coolant_control.h"
#include "spindle_control.h"
#include "stepper.h"
#include "nvs.h"
#include "stream.h"
#include "probe.h"
#include "plugins.h"
#include "settings.h"
#include "report.h"
#define HAL_VERSION 8
// driver capabilities, to be set by driver in driver_init(), flags may be cleared after to switch off option
typedef union {
uint32_t value;
struct {
uint32_t mist_control :1,
variable_spindle :1,
spindle_dir :1,
software_debounce :1,
step_pulse_delay :1,
limits_pull_up :1,
control_pull_up :1,
probe_pull_up :1,
amass_level :2, // 0...3
spindle_at_speed :1,
laser_ppi_mode :1,
spindle_sync :1,
sd_card :1,
bluetooth :1,
ethernet :1,
wifi :1,
spindle_pwm_invert :1,
spindle_pid :1,
mpg_mode :1,
spindle_pwm_linearization :1,
atc :1,
no_gcode_message_handling :1,
dual_spindle :1,
odometers :1,
unassigned :7;
};
} driver_cap_t;
typedef void (*driver_reset_ptr)(void);
// I/O stream
typedef void (*stream_write_ptr)(const char *s);
typedef bool (*enqueue_realtime_command_ptr)(char data);
typedef struct {
stream_type_t type;
uint16_t (*get_rx_buffer_available)(void);
// bool (*stream_write)(char c);
stream_write_ptr write; // write string to current I/O stream only.
stream_write_ptr write_all; // write string to all active output streams.
int16_t (*read)(void);
void (*reset_read_buffer)(void);
void (*cancel_read_buffer)(void);
bool (*suspend_read)(bool await);
enqueue_realtime_command_ptr enqueue_realtime_command; // NOTE: set by grbl at startup.
} io_stream_t;
typedef struct {
uint8_t num_digital_in;
uint8_t num_digital_out;
uint8_t num_analog_in;
uint8_t num_analog_out;
void (*digital_out)(uint8_t port, bool on);
bool (*analog_out)(uint8_t port, float value);
int32_t (*wait_on_input)(bool digital, uint8_t port, wait_mode_t wait_mode, float timeout);
} io_port_t;
// Spindle
typedef void (*spindle_set_state_ptr)(spindle_state_t state, float rpm);
typedef spindle_state_t (*spindle_get_state_ptr)(void);
#ifdef SPINDLE_PWM_DIRECT
typedef uint_fast16_t (*spindle_get_pwm_ptr)(float rpm);
typedef void (*spindle_update_pwm_ptr)(uint_fast16_t pwm);
#else
typedef void (*spindle_update_rpm_ptr)(float rpm);
#endif
typedef spindle_data_t *(*spindle_get_data_ptr)(spindle_data_request_t request);
typedef void (*spindle_reset_data_ptr)(void);
typedef void (*spindle_pulse_on_ptr)(uint_fast16_t pulse_length);
typedef struct {
spindle_set_state_ptr set_state;
spindle_get_state_ptr get_state;
#ifdef SPINDLE_PWM_DIRECT
spindle_get_pwm_ptr get_pwm;
spindle_update_pwm_ptr update_pwm;
#else
spindle_update_rpm_ptr update_rpm;
#endif
// Optional entry points:
spindle_get_data_ptr get_data;
spindle_reset_data_ptr reset_data;
spindle_pulse_on_ptr pulse_on;
} spindle_ptrs_t;
// Coolant
typedef void (*coolant_set_state_ptr)(coolant_state_t mode);
typedef coolant_state_t (*coolant_get_state_ptr)(void);
typedef struct {
coolant_set_state_ptr set_state;
coolant_get_state_ptr get_state;
} coolant_ptrs_t;
// Limits
typedef void (*limits_enable_ptr)(bool on, bool homing);
typedef limit_signals_t (*limits_get_state_ptr)(void);
typedef void (*limit_interrupt_callback_ptr)(limit_signals_t state);
typedef struct {
limits_enable_ptr enable;
limits_get_state_ptr get_state;
limit_interrupt_callback_ptr interrupt_callback; // set up by core before driver_init() is called.
} limits_ptrs_t;
// Homing
typedef struct {
limits_get_state_ptr get_state;
} homing_ptrs_t;
// Control signals
typedef control_signals_t (*control_signals_get_state_ptr)(void);
typedef void (*control_signals_callback_ptr)(control_signals_t signals);
typedef struct {
control_signals_get_state_ptr get_state;
control_signals_callback_ptr interrupt_callback; // set up by core before driver_init() is called.
} control_signals_ptrs_t;
// Steppers
typedef void (*stepper_wake_up_ptr)(void);
typedef void (*stepper_go_idle_ptr)(bool clear_signals);
typedef void (*stepper_enable_ptr)(axes_signals_t enable);
typedef void (*stepper_disable_motors_ptr)(axes_signals_t axes, squaring_mode_t mode);
typedef void (*stepper_cycles_per_tick_ptr)(uint32_t cycles_per_tick);
typedef void (*stepper_pulse_start_ptr)(stepper_t *stepper);
typedef void (*stepper_output_step_ptr)(axes_signals_t step_outbits, axes_signals_t dir_outbits);
typedef axes_signals_t (*stepper_get_auto_squared_ptr)(void);
typedef void (*stepper_interrupt_callback_ptr)(void);
typedef struct {
stepper_wake_up_ptr wake_up;
stepper_go_idle_ptr go_idle;
stepper_enable_ptr enable;
stepper_disable_motors_ptr disable_motors;
stepper_cycles_per_tick_ptr cycles_per_tick;
stepper_pulse_start_ptr pulse_start;
stepper_interrupt_callback_ptr interrupt_callback; // set up by core before driver_init() is called.
// Optional entry points:
stepper_get_auto_squared_ptr get_auto_squared;
stepper_output_step_ptr output_step;
} stepper_ptrs_t;
// Probe (optional)
typedef probe_state_t (*probe_get_state_ptr)(void);
typedef void (*probe_configure_ptr)(bool is_probe_away, bool probing);
typedef void (*probe_connected_toggle_ptr)(void);
typedef struct {
probe_configure_ptr configure;
probe_get_state_ptr get_state;
probe_connected_toggle_ptr connected_toggle;
} probe_ptrs_t;
typedef void (*tool_select_ptr)(tool_data_t *tool, bool next);
typedef status_code_t (*tool_change_ptr)(parser_state_t *gc_state);
typedef struct {
tool_select_ptr select;
tool_change_ptr change;
} tool_ptrs_t;
// User M-codes (optional)
typedef user_mcode_t (*user_mcode_check_ptr)(user_mcode_t mcode);
typedef status_code_t (*user_mcode_validate_ptr)(parser_block_t *gc_block, parameter_words_t *parameter_words);
typedef void (*user_mcode_execute_ptr)(sys_state_t state, parser_block_t *gc_block);
typedef struct {
user_mcode_check_ptr check;
user_mcode_validate_ptr validate;
user_mcode_execute_ptr execute;
} user_mcode_ptrs_t;
// Encoder (optional)
typedef uint8_t (*encoder_get_n_encoders_ptr)(void);
typedef void (*encoder_on_event_ptr)(encoder_t *encoder, int32_t position);
typedef void (*encoder_reset_ptr)(uint_fast8_t id);
typedef struct {
encoder_get_n_encoders_ptr get_n_encoders;
encoder_on_event_ptr on_event;
encoder_reset_ptr reset;
} encoder_ptrs_t;
//
// main HAL structure
typedef struct {
uint32_t version;
char *info;
char *driver_version;
char *driver_options;
char *board;
uint32_t f_step_timer;
uint32_t rx_buffer_size;
uint32_t max_step_rate;
uint8_t driver_axis_settings;
bool (*driver_setup)(settings_t *settings);
void (*delay_ms)(uint32_t ms, void (*callback)(void));
void (*set_bits_atomic)(volatile uint_fast16_t *value, uint_fast16_t bits);
uint_fast16_t (*clear_bits_atomic)(volatile uint_fast16_t *value, uint_fast16_t bits);
uint_fast16_t (*set_value_atomic)(volatile uint_fast16_t *value, uint_fast16_t bits);
void (*irq_enable)(void);
void (*irq_disable)(void);
limits_ptrs_t limits;
homing_ptrs_t homing;
coolant_ptrs_t coolant;
spindle_ptrs_t spindle;
stepper_ptrs_t stepper;
control_signals_ptrs_t control;
io_stream_t stream;
settings_changed_ptr settings_changed;
//
// optional entry points, may be unassigned (null)
//
bool (*driver_release)(void);
bool (*get_position)(int32_t (*position)[N_AXIS]);
uint32_t (*get_elapsed_ticks)(void);
void (*pallet_shuttle)(void);
void (*reboot)(void);
#ifdef DEBUGOUT
void (*debug_out)(bool on);
#endif
probe_ptrs_t probe;
user_mcode_ptrs_t user_mcode;
driver_reset_ptr driver_reset;
tool_ptrs_t tool;
encoder_ptrs_t encoder;
nvs_io_t nvs;
io_port_t port;
bool (*stream_blocking_callback)(void); // set up by core before driver_init() is called.
// driver capabilities flags
driver_cap_t driver_cap;
control_signals_t signals_cap;
} grbl_hal_t;
// TODO: move the following structs to grbl.h?
/* TODO: add to grbl pointers so that a different formatting (xml, json etc) of reports may be implemented by driver?
typedef struct {
status_code_t (*report_status_message)(status_code_t status_code);
alarm_code_t (*report_alarm_message)(alarm_code_t alarm_code);
message_code_t (*report_feedback_message)(message_code_t message_code);
void (*report_init_message)(void);
void (*report_grbl_help)(void);
void (*report_echo_line_received)(char *line);
void (*report_realtime_status)(void);
void (*report_probe_parameters)(void);
void (*report_ngc_parameters)(void);
void (*report_gcode_modes)(void);
void (*report_startup_line)(uint8_t n, char *line);
void (*report_execute_startup_message)(char *line, status_code_t status_code);
} grbl_report_t;
*/
// Report entry points set by core at reset.
typedef status_code_t (*status_message_ptr)(status_code_t status_code);
typedef message_code_t (*feedback_message_ptr)(message_code_t message_code);
typedef struct {
setting_output_ptr setting;
status_message_ptr status_message;
feedback_message_ptr feedback_message;
} report_t;
// Core event handler and other entry points.
// Most of the event handlers defaults to NULL, a few is set up to call a dummy handler for simpler code.
typedef void (*on_state_change_ptr)(sys_state_t state);
typedef void (*on_probe_completed_ptr)(void);
typedef void (*on_program_completed_ptr)(program_flow_t program_flow);
typedef void (*on_execute_realtime_ptr)(sys_state_t state);
typedef void (*on_unknown_accessory_override_ptr)(uint8_t cmd);
typedef void (*on_report_options_ptr)(bool newopt);
typedef void (*on_report_command_help_ptr)(void);
typedef void (*on_global_settings_restore_ptr)(void);
typedef setting_details_t *(*on_get_settings_ptr)(void); // NOTE: this must match the signature of the same definition in
// the setting_details_t structure in settings.h!
typedef void (*on_realtime_report_ptr)(stream_write_ptr stream_write, report_tracking_flags_t report);
typedef void (*on_unknown_feedback_message_ptr)(stream_write_ptr stream_write);
typedef bool (*on_laser_ppi_enable_ptr)(uint_fast16_t ppi, uint_fast16_t pulse_length);
typedef status_code_t (*on_unknown_sys_command_ptr)(sys_state_t state, char *line); // return Status_Unhandled.
typedef status_code_t (*on_user_command_ptr)(char *line);
typedef sys_commands_t *(*on_get_commands_ptr)(void);
typedef struct {
// report entry points set by core at reset.
report_t report;
// grbl core events - may be subscribed to by drivers or by the core.
on_state_change_ptr on_state_change;
on_probe_completed_ptr on_probe_completed;
on_program_completed_ptr on_program_completed;
on_execute_realtime_ptr on_execute_realtime;
on_unknown_accessory_override_ptr on_unknown_accessory_override;
on_report_options_ptr on_report_options;
on_report_command_help_ptr on_report_command_help;
on_global_settings_restore_ptr on_global_settings_restore;
on_get_settings_ptr on_get_settings;
on_realtime_report_ptr on_realtime_report;
on_unknown_feedback_message_ptr on_unknown_feedback_message;
on_unknown_sys_command_ptr on_unknown_sys_command; // return Status_Unhandled if not handled.
on_get_commands_ptr on_get_commands;
on_user_command_ptr on_user_command;
on_laser_ppi_enable_ptr on_laser_ppi_enable;
// core entry points - set up by core before driver_init() is called.
bool (*protocol_enqueue_gcode)(char *data);
} grbl_t;
extern grbl_t grbl;
extern grbl_hal_t hal;
extern bool driver_init (void);
#endif
+36
View File
@@ -0,0 +1,36 @@
/*
kinematics.h - kinematics interface (API)
Part of grblHAL
Copyright (c) 2019 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _KINEMATICS_H_
#define _KINEMATICS_H_
typedef struct {
void (*convert_array_steps_to_mpos)(float *position, int32_t *steps);
void (*plan_target_to_steps) (int32_t *target_steps, float *target);
bool (*segment_line) (float *target, plan_line_data_t *pl_data, bool init);
uint_fast8_t (*limits_get_axis_mask)(uint_fast8_t idx);
void (*limits_set_target_pos)(uint_fast8_t idx);
void (*limits_set_machine_positions)(axes_signals_t cycle);
} kinematics_t;
extern kinematics_t kinematics;
#endif
+541
View File
File diff suppressed because it is too large Load Diff
+46
View File
@@ -0,0 +1,46 @@
/*
limits.h - code pertaining to limit-switches and performing the homing cycle
Part of grblHAL
Copyright (c) 2017-2018 Terje Io
Copyright (c) 2012-2015 Sungeun K. Jeon
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _LIMITS_H_
#define _LIMITS_H_
#include "nuts_bolts.h"
// Perform one portion of the homing cycle based on the input settings.
bool limits_go_home(axes_signals_t cycle);
// Check for soft limit violations
void limits_soft_check(float *target);
// Check if homing is required.
bool limits_homing_required (void);
// Set axes to be homed from settings.
void limits_set_homing_axes (void);
void limits_set_machine_positions (axes_signals_t cycle, bool add_pulloff);
void limit_interrupt_handler (limit_signals_t state);
axes_signals_t limit_signals_merge (limit_signals_t signals);
#endif
+676
View File
File diff suppressed because it is too large Load Diff
+161
View File
@@ -0,0 +1,161 @@
/*
maslow.h - Maslow router kinematics implementation
Part of grblHAL
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 <http://www.gnu.org/licenses/>.
The basis for this code has been pulled from MaslowDue created by Larry D O'Cull.
<https://github.com/ldocull/MaslowDue>
Some portions of that package directly or indirectly has been pulled from from the Maslow CNC
firmware for Aduino Mega. Those parts are Copyright 2014-2017 Bar Smith.
<https://www.maslowcnc.com/>
It has been adapted for grbl by Terje Io.
*** TO BE COMPLETED ***
*/
#include "grbl.h"
#ifndef _MASLOW_H_
#define _MASLOW_H_
#define FP_SCALING 1024.0f
#define SPROCKET_RADIUS_MM (10.1f)
#define MAX_SEG_LENGTH_MM 2.0f /* long lines must be segmented due to circular motion */
// PID position loop factors X: Kp = 25000 Ki = 15000 Kd = 22000 Imax = 5000
// 14.000 fixed point arithmatic S13.10
#ifdef DRIVER_TLE5206
#define MASLOW_A_KP 10.0f
#define MASLOW_A_KI 21.0f
#define MASLOW_A_KD 18.0f
#define MASLOW_A_IMAX 5000
#define MASLOW_B_KP 10.0f
#define MASLOW_B_KI 21.0f
#define MASLOW_B_KD 18.0f
#define MASLOW_B_IMAX 5000
#define MASLOW_Z_KP 10.0f
#define MASLOW_Z_KI 21.0f
#define MASLOW_Z_KD 17.0f
#define MASLOW_Z_IMAX 5000
#else
#define MASLOW_A_KP 22.0f
#define MASLOW_A_KI 17.0f
#define MASLOW_A_KD 20.0f
#define MASLOW_A_IMAX 5000
#define MASLOW_B_KP 22.0f
#define MASLOW_B_KI 17.0f
#define MASLOW_B_KD 20.0f
#define MASLOW_B_IMAX 5000
#define MASLOW_Z_KP 20.0f
#define MASLOW_Z_KI 17.0f
#define MASLOW_Z_KD 18.0f
#define MASLOW_Z_IMAX 5000
#endif
#define MASLOW_MACHINEWIDTH 2400.0f
#define MASLOW_MACHINEHEIGHT 1200.0f
#define MASLOW_DISTBETWEENMOTORS 3000.0f
#define MASLOW_MOTOROFFSETY 600.0f
#define MASLOW_CHAINLENGTH 3000.0f
#define MASLOW_CHAINOVERSPROCKET 0
#define MASLOW_CHAINSAGCORRECTION 59.504839f
#define MASLOW_LEFTCHAINTOLERANCE 0.0f
#define MASLOW_RIGHTCHAINTOLERANCE 0.0f
#define MASLOW_ROTATIONDISKRADIUS 104.3f
#define MASLOW_SLEDHEIGHT 139.0f
#define MASLOW_SLEDWIDTH 310.0f
#define MASLOW_ACORRSCALING 1.003922f
#define MASLOW_BCORRSCALING 1.002611f
typedef enum {
Maslow_ChainOverSprocket = 260,
Maslow_MachineWidth,
Maslow_MachineHeight,
Maslow_DistBetweenMotors,
Maslow_MotorOffsetY,
Maslow_AcorrScaling,
Maslow_BcorrScaling,
Maslow_SettingMax,
} maslow_setting_t;
typedef enum {
AxisSetting_MaslowKP = 10,
AxisSetting_MaslowKI,
AxisSetting_MaslowKD,
AxisSetting_MaslowIMax,
AxisSetting_MaslowMaxSetting
} maslow_axis_setting_t;
typedef struct {
float Kp;
float Ki;
float Kd;
float Imax;
} maslow_pid_coefficients_t;
typedef struct {
maslow_pid_coefficients_t pid[N_AXIS];
uint32_t chainOverSprocket;
float machineWidth; /* Maslow specific settings */
float machineHeight;
float distBetweenMotors;
float motorOffsetY;
float chainSagCorrection;
float leftChainTolerance;
float rightChainTolerance;
float rotationDiskRadius;
float chainLength;
float sledHeight;
float sledWidth;
float XcorrScaling;
float YcorrScaling;
} maslow_settings_t;
typedef struct {
float Error;
float Integral;
float iterm;
float DiffTerm;
float speed;
} maslow_debug_t;
typedef struct {
maslow_settings_t settings;
void (*pid_settings_changed)(uint_fast8_t idx);
void (*move)(uint_fast8_t idx, int_fast16_t distance);
void (*reset_pid)(uint_fast8_t idx);
void (*pos_enable)(bool enable);
void (*tuning_enable)(bool enable);
int32_t (*set_step_size)(uint_fast8_t idx, int32_t step_size);
maslow_debug_t *(*get_debug_data)(uint_fast8_t idx);
} maslow_hal_t;
extern maslow_hal_t maslow_hal;
// Initialize HAL pointers for Maslow Router kinematics
bool maslow_init (void);
static status_code_t maslow_tuning (uint_fast16_t state, char *line);
#endif
+989
View File
File diff suppressed because it is too large Load Diff
+82
View File
@@ -0,0 +1,82 @@
/*
motion_control.h - high level interface for issuing motion commands
Part of grblHAL
Copyright (c) 2017-2019 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _MOTION_CONTROL_H_
#define _MOTION_CONTROL_H_
// System motion commands must have a line number of zero.
#define HOMING_CYCLE_LINE_NUMBER 0
#define PARKING_MOTION_LINE_NUMBER 0
#define HOMING_CYCLE_ALL 0 // Must be zero.
#define HOMING_CYCLE_X bit(X_AXIS)
#define HOMING_CYCLE_Y bit(Y_AXIS)
#define HOMING_CYCLE_Z bit(Z_AXIS)
// Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second
// unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in
// (1 minute)/feed_rate time.
bool mc_line(float *target, plan_line_data_t *pl_data);
// Execute an arc in offset mode format. position == current xyz, target == target xyz,
// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is
// the direction of helical travel, radius == circle radius, is_clockwise_arc boolean. Used
// for vector transformation direction.
void mc_arc(float *target, plan_line_data_t *pl_data, float *position, float *offset, float radius,
plane_t plane, bool is_clockwise_arc);
// Execute canned cycle (drill)
void mc_canned_drill (motion_mode_t motion, float *target, plan_line_data_t *pl_data, float *position, plane_t plane, uint32_t repeats, gc_canned_t *canned);
// Execute canned cycle (threading)
void mc_thread (plan_line_data_t *pl_data, float *position, gc_thread_data *thread, bool feed_hold_disabled);
// Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog.
status_code_t mc_jog_execute(plan_line_data_t *pl_data, parser_block_t *gc_block);
// Dwell for a specific number of seconds
void mc_dwell(float seconds);
// Perform homing cycle to locate machine zero. Requires limit switches.
status_code_t mc_homing_cycle(axes_signals_t cycle);
// Perform tool length probe cycle. Requires probe switch.
gc_probe_t mc_probe_cycle(float *target, plan_line_data_t *pl_data, gc_parser_flags_t parser_flags);
// Handles updating the override control state.
void mc_override_ctrl_update(gc_override_flags_t override_state);
// Plans and executes the single special motion case for parking. Independent of main planner buffer.
bool mc_parking_motion(float *parking_target, plan_line_data_t *pl_data);
void mc_cubic_b_spline(float *target, plan_line_data_t *pl_data, float *position, float *offset1, float *offset2);
// Performs system reset. If in motion state, kills all motion and sets system alarm.
void mc_reset();
#ifdef ENABLE_BACKLASH_COMPENSATION
void mc_backlash_init (void);
void mc_sync_backlash_position (void);
#endif
#endif
+27
View File
@@ -0,0 +1,27 @@
/*
my_plugin.c - An embedded CNC Controller with rs274/ngc (g-code) support
"Dummy" user plugin init, called if no user plugin is provided.
Part of grblHAL
Copyright (c) 2020 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
__attribute__((weak)) void my_plugin_init (void)
{
// NOOP
}
+293
View File
@@ -0,0 +1,293 @@
/*
nuts_bolts.c - Shared functions
Part of grblHAL
Copyright (c) 2017-2021 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include <stdint.h>
#include <stdbool.h>
#include "hal.h"
#include "protocol.h"
#include "state_machine.h"
#include "nuts_bolts.h"
#ifndef DWELL_TIME_STEP
#define DWELL_TIME_STEP 50 // Integer (1-255) (milliseconds)
#endif
#define MAX_PRECISION 10
static char buf[STRLEN_COORDVALUE + 1];
static const float froundvalues[MAX_PRECISION + 1] =
{
0.5, // 0
0.05, // 1
0.005, // 2
0.0005, // 3
0.00005, // 4
0.000005, // 5
0.0000005, // 6
0.00000005, // 7
0.000000005, // 8
0.0000000005, // 9
0.00000000005 // 10
};
char const *const axis_letter[N_AXIS] = {
"X",
"Y",
"Z"
#if N_AXIS > 3
,"A"
#endif
#if N_AXIS > 4
,"B"
#endif
#if N_AXIS > 5
,"C"
#endif
};
// Converts an uint32 variable to string.
char *uitoa (uint32_t n)
{
char *bptr = buf + sizeof(buf);
*--bptr = '\0';
if (n == 0)
*--bptr = '0';
else while (n) {
*--bptr = '0' + (n % 10);
n /= 10;
}
return bptr;
}
// Convert float to string by immediately converting to integers.
// Number of decimal places, which are tracked by a counter, must be set by the user.
// The integers is then efficiently converted to a string.
char *ftoa (float n, uint8_t decimal_places)
{
bool isNegative;
char *bptr = buf + sizeof(buf);
*--bptr = '\0';
if ((isNegative = n < 0.0f))
n = -n;
n += froundvalues[decimal_places];
uint32_t a = (uint32_t)n;
if (decimal_places) {
n -= (float)a;
uint_fast8_t decimals = decimal_places;
while (decimals >= 2) { // Quickly convert values expected to be E0 to E-4.
n *= 100.0f;
decimals -= 2;
}
if (decimals)
n *= 10.0f;
uint32_t b = (uint32_t)n;
while(decimal_places--) {
if(b) {
*--bptr = (b % 10) + '0'; // Get digit
b /= 10;
} else
*--bptr = '0';
}
}
*--bptr = '.'; // Always add decimal point (TODO: is this really needed?)
if(a == 0)
*--bptr = '0';
else while(a) {
*--bptr = (a % 10) + '0'; // Get digit
a /= 10;
}
if(isNegative)
*--bptr = '-';
return bptr;
}
// Extracts a floating point value from a string. The following code is based loosely on
// the avr-libc strtod() function by Michael Stumpf and Dmitry Xmelkov and many freely
// available conversion method examples, but has been highly optimized for Grbl. For known
// CNC applications, the typical decimal value is expected to be in the range of E0 to E-4.
// Scientific notation is officially not supported by g-code, and the 'E' character may
// be a g-code word on some CNC systems. So, 'E' notation will not be recognized.
// NOTE: Thanks to Radu-Eosif Mihailescu for identifying the issues with using strtod().
bool read_float (char *line, uint_fast8_t *char_counter, float *float_ptr)
{
char *ptr = line + *char_counter;
int_fast8_t exp = 0;
uint_fast8_t ndigit = 0, c;
uint32_t intval = 0;
bool isnegative, isdecimal = false;
// Grab first character and increment pointer. No spaces assumed in line.
c = *ptr++;
// Capture initial positive/minus character
if ((isnegative = (c == '-')) || c == '+')
c = *ptr++;
// Extract number into fast integer. Track decimal in terms of exponent value.
while(c) {
c -= '0';
if (c <= 9) {
ndigit++;
if (ndigit <= MAX_INT_DIGITS) {
if (isdecimal)
exp--;
intval = (((intval << 2) + intval) << 1) + c; // intval*10 + c
} else if (!isdecimal)
exp++; // Drop overflow digits
} else if (c == (uint_fast8_t)('.' - '0') && !isdecimal)
isdecimal = true;
else
break;
c = *ptr++;
}
// Return if no digits have been read.
if (!ndigit)
return false;
// Convert integer into floating point.
float fval = (float)intval;
// Apply decimal. Should perform no more than two floating point multiplications for the
// expected range of E0 to E-4.
if (fval != 0.0f) {
while (exp <= -2) {
fval *= 0.01f;
exp += 2;
}
if (exp < 0)
fval *= 0.1f;
else if (exp > 0) do {
fval *= 10.0f;
} while (--exp > 0);
}
// Assign floating point value with correct sign.
*float_ptr = isnegative ? - fval : fval;
*char_counter = ptr - line - 1; // Set char_counter to next statement
return true;
}
// Returns true if float value is a whole number (integer)
bool isintf (float value)
{
return value != NAN && fabsf(value - truncf(value)) < 0.001f;
}
// Non-blocking delay function used for general operation and suspend features.
void delay_sec (float seconds, delaymode_t mode)
{
uint_fast16_t i = (uint_fast16_t)ceilf((1000.0f / DWELL_TIME_STEP) * seconds) + 1;
while (--i && !sys.abort) {
if (mode == DelayMode_Dwell) {
protocol_execute_realtime();
} else { // DelayMode_SysSuspend
// Execute rt_system() only to avoid nesting suspend loops.
protocol_exec_rt_system();
if (state_door_reopened()) // Bail, if safety door reopens.
return;
}
hal.delay_ms(DWELL_TIME_STEP, 0); // Delay DWELL_TIME_STEP increment
}
}
float convert_delta_vector_to_unit_vector (float *vector)
{
uint_fast8_t idx = N_AXIS;
float magnitude = 0.0f, inv_magnitude;
do {
if (vector[--idx] != 0.0f)
magnitude += vector[idx] * vector[idx];
} while(idx);
idx = N_AXIS;
magnitude = sqrtf(magnitude);
inv_magnitude = 1.0f / magnitude;
do {
vector[--idx] *= inv_magnitude;
} while(idx);
return magnitude;
}
// calculate checksum byte for data
uint8_t calc_checksum (uint8_t *data, uint32_t size) {
uint8_t checksum = 0;
while(size--) {
checksum = (checksum << 1) | (checksum >> 7);
checksum += *(data++);
}
return checksum;
}
// Remove spaces from and convert string to uppercase (in situ)
char *strcaps (char *s)
{
char c, *s1 = s, *s2 = s;
do {
c = *s1++;
if(c != ' ')
*s2++ = CAPS(c);
} while(c);
*s2 = '\0';
return s;
}
void dummy_handler (void)
{
// NOOP
}
+176
View File
@@ -0,0 +1,176 @@
/*
nuts_bolts.h - Header file for shared definitions, variables, and functions
Part of grblHAL
Copyright (c) 2017-2021 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _NUTS_BOLTS_H_
#define _NUTS_BOLTS_H_
#include "grbl.h"
#ifndef true
#define false 0
#define true 1
#endif
#define Off 0
#define On 1
#define SOME_LARGE_VALUE 1.0E+38f
#ifndef M_PI
#define M_PI 3.14159265358979323846f
#endif
#define TAN_30 0.57735f // Used for threading calculations (60 degree inserts)
#define RADDEG 0.0174532925f // Radians per degree
#define ABORTED (sys.abort || sys.cancel)
// Convert character to uppercase
#define CAPS(c) ((c >= 'a' && c <= 'z') ? c & 0x5F : c)
#ifndef STM32F103xB
#ifndef UNUSED
#define UNUSED(x) (void)(x)
#endif
#endif
// Axis array index values. Must start with 0 and be continuous.
#define X_AXIS 0 // Axis indexing value.
#define Y_AXIS 1
#define Z_AXIS 2
#define X_AXIS_BIT bit(X_AXIS)
#define Y_AXIS_BIT bit(Y_AXIS)
#define Z_AXIS_BIT bit(Z_AXIS)
#if N_AXIS > 3
#define A_AXIS 3
#define A_AXIS_BIT bit(A_AXIS)
#endif
#if N_AXIS > 4
#define B_AXIS 4
#define B_AXIS_BIT bit(B_AXIS)
#endif
#if N_AXIS == 6
#define C_AXIS 5
#define C_AXIS_BIT bit(C_AXIS)
#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|A_AXIS_BIT|B_AXIS_BIT|C_AXIS_BIT)
#endif
#if N_AXIS == 3
#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT)
#elif N_AXIS == 4
#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|A_AXIS_BIT)
#elif N_AXIS == 5
#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|A_AXIS_BIT|B_AXIS_BIT)
#endif
extern char const *const axis_letter[];
typedef union {
uint8_t mask;
uint8_t value;
struct {
uint8_t x :1,
y :1,
z :1,
a :1,
b :1,
c :1;
};
} axes_signals_t;
#pragma pack(push, 1)
typedef struct {
axes_signals_t min;
axes_signals_t max;
axes_signals_t min2;
axes_signals_t max2;
} limit_signals_t;
#pragma pack(pop)
typedef enum {
DelayMode_Dwell = 0,
DelayMode_SysSuspend
} delaymode_t;
// Delay struct, currently not used by core - may be used by drivers
typedef struct {
volatile uint32_t ms;
void (*callback)(void);
} delay_t;
// Conversions
#define MM_PER_INCH (25.40f)
#define INCH_PER_MM (0.0393701f)
#define MAX_INT_DIGITS 8 // Maximum number of digits in int32 (and float)
#define STRLEN_COORDVALUE (MAX_INT_DIGITS + N_DECIMAL_COORDVALUE_INCH + 1) // 8.4 format - excluding terminating null
// Useful macros
#define clear_vector(a) memset(a, 0, sizeof(a))
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#define isequal_position_vector(a,b) !memcmp(a, b, sizeof(coord_data_t))
// Bit field and masking macros
#ifndef bit
#define bit(n) (1UL << n)
#endif
#define bit_true(x,mask) (x) |= (mask)
#define bit_false(x,mask) (x) &= ~(mask)
#define BIT_SET(x, bit, v) { if (v) { x |= (bit); } else { x &= ~(bit); } }
#define bit_istrue(x, mask) ((x & (mask)) != 0)
#define bit_isfalse(x, mask) ((x & (mask)) == 0)
// Converts an uint32 variable to string.
char *uitoa (uint32_t n);
// Converts a float variable to string with the specified number of decimal places.
char *ftoa (float n, uint8_t decimal_places);
// Returns true if float value is a whole number (integer)
bool isintf (float value);
// Read a floating point value from a string. Line points to the input buffer, char_counter
// is the indexer pointing to the current character of the line, while float_ptr is
// a pointer to the result variable. Returns true when it succeeds
bool read_float(char *line, uint_fast8_t *char_counter, float *float_ptr);
// Non-blocking delay function used for general operation and suspend features.
void delay_sec(float seconds, delaymode_t mode);
float convert_delta_vector_to_unit_vector(float *vector);
// calculate checksum byte for data
uint8_t calc_checksum (uint8_t *data, uint32_t size);
char *strcaps (char *s);
void dummy_handler (void);
#endif
+77
View File
@@ -0,0 +1,77 @@
/*
nvs.h - non-volative storage data structures
Part of grblHAL
Copyright (c) 2017-2020 Terje Io
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _NVS_H_
#define _NVS_H_
#ifndef NVS_SIZE
#define NVS_SIZE 2048
#endif
#define GRBL_NVS_SIZE 1024
#define NVS_CRC_BYTES 1
// Define persistent storage memory address location values for Grbl settings and parameters
// NOTE: 1KB persistent storage is the minimum required. The upper half is reserved for parameters and
// the startup script. The lower half contains the global settings and space for future
// developments.
#define NVS_ADDR_GLOBAL 1U
#define NVS_ADDR_PARAMETERS 512U
#define NVS_ADDR_BUILD_INFO 942U
#define NVS_ADDR_STARTUP_BLOCK (NVS_ADDR_BUILD_INFO - 1 - N_STARTUP_LINE * (sizeof(stored_line_t) + NVS_CRC_BYTES))
#ifdef N_TOOLS
#define NVS_ADDR_TOOL_TABLE (NVS_ADDR_PARAMETERS - 1 - N_TOOLS * (sizeof(tool_data_t) + NVS_CRC_BYTES))
#endif
typedef enum {
NVS_None = 0,
NVS_EEPROM,
NVS_FRAM,
NVS_Flash,
NVS_Emulated
} nvs_type;
typedef struct {
uint8_t *mem_address;
uint16_t address;
uint16_t size;
} nvs_driver_area_t;
typedef enum {
NVS_TransferResult_Failed = 0,
NVS_TransferResult_Busy,
NVS_TransferResult_OK,
} nvs_transfer_result_t;
typedef struct {
nvs_type type;
uint16_t size;
nvs_driver_area_t driver_area;
uint8_t (*get_byte)(uint32_t addr);
void (*put_byte)(uint32_t addr, uint8_t new_value);
nvs_transfer_result_t (*memcpy_to_nvs)(uint32_t destination, uint8_t *source, uint32_t size, bool with_checksum);
nvs_transfer_result_t (*memcpy_from_nvs)(uint8_t *destination, uint32_t source, uint32_t size, bool with_checksum);
bool (*memcpy_from_flash)(uint8_t *dest);
bool (*memcpy_to_flash)(uint8_t *source);
} nvs_io_t;
#endif
+387
View File
@@ -0,0 +1,387 @@
/*
nvs_buffer.c - RAM based non-volatile storage buffer/emulation
Part of grblHAL
Copyright (c) 2017-2021 Terje Io
Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
//
// Can be used by MCUs with no nonvolatile storage options, be sure to allocate enough heap memory before use
//
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "hal.h"
#include "nvs_buffer.h"
#include "protocol.h"
static uint8_t *nvsbuffer = NULL;
static nvs_io_t physical_nvs;
static bool dirty;
settings_dirty_t settings_dirty;
typedef struct {
uint16_t addr;
uint8_t type;
uint8_t offset;
} emap_t;
#define NVS_GROUP_GLOBAL 0
#define NVS_GROUP_TOOLS 1
#define NVS_GROUP_PARAMETERS 2
#define NVS_GROUP_STARTUP 3
#define NVS_GROUP_BUILD 4
#define PARAMETER_ADDR(n) (NVS_ADDR_PARAMETERS + n * (sizeof(coord_data_t) + NVS_CRC_BYTES))
#define STARTLINE_ADDR(n) (NVS_ADDR_STARTUP_BLOCK + n * (sizeof(stored_line_t) + NVS_CRC_BYTES))
#ifdef N_TOOLS
#define TOOL_ADDR(n) (NVS_ADDR_TOOL_TABLE + n * (sizeof(tool_data_t) + NVS_CRC_BYTES))
#endif
static const emap_t target[] = {
{NVS_ADDR_GLOBAL, NVS_GROUP_GLOBAL, 0},
#ifdef N_TOOLS
{TOOL_ADDR(0), NVS_GROUP_TOOLS, 0},
{TOOL_ADDR(1), NVS_GROUP_TOOLS, 1},
{TOOL_ADDR(2), NVS_GROUP_TOOLS, 2},
{TOOL_ADDR(3), NVS_GROUP_TOOLS, 3},
{TOOL_ADDR(4), NVS_GROUP_TOOLS, 4},
{TOOL_ADDR(5), NVS_GROUP_TOOLS, 5},
{TOOL_ADDR(6), NVS_GROUP_TOOLS, 6},
{TOOL_ADDR(7), NVS_GROUP_TOOLS, 7},
#if N_TOOL > 8
#error Increase number of tool entries!
#endif
#endif
{PARAMETER_ADDR(0), NVS_GROUP_PARAMETERS, 0},
{PARAMETER_ADDR(1), NVS_GROUP_PARAMETERS, 1},
{PARAMETER_ADDR(2), NVS_GROUP_PARAMETERS, 2},
{PARAMETER_ADDR(3), NVS_GROUP_PARAMETERS, 3},
{PARAMETER_ADDR(4), NVS_GROUP_PARAMETERS, 4},
{PARAMETER_ADDR(5), NVS_GROUP_PARAMETERS, 5},
{PARAMETER_ADDR(6), NVS_GROUP_PARAMETERS, 6},
{PARAMETER_ADDR(7), NVS_GROUP_PARAMETERS, 7},
{PARAMETER_ADDR(8), NVS_GROUP_PARAMETERS, 8},
{PARAMETER_ADDR(9), NVS_GROUP_PARAMETERS, 9},
{PARAMETER_ADDR(10), NVS_GROUP_PARAMETERS, 10},
{PARAMETER_ADDR(11), NVS_GROUP_PARAMETERS, 11},
{STARTLINE_ADDR(0), NVS_GROUP_STARTUP, 0},
{STARTLINE_ADDR(1), NVS_GROUP_STARTUP, 1},
#if N_STARTUP_LINE > 2
#error Increase number of startup line entries!
#endif
{NVS_ADDR_BUILD_INFO, NVS_GROUP_BUILD, 0},
{0, 0, 0} // list termination - do not remove
};
inline static uint8_t ram_get_byte (uint32_t addr)
{
return nvsbuffer[addr];
}
inline static void ram_put_byte (uint32_t addr, uint8_t new_value)
{
dirty = dirty || nvsbuffer[addr] != new_value;
nvsbuffer[addr] = new_value;
}
// Extensions added as part of Grbl
static nvs_transfer_result_t memcpy_to_ram (uint32_t destination, uint8_t *source, uint32_t size, bool with_checksum)
{
if(hal.nvs.driver_area.address && destination > hal.nvs.driver_area.address + hal.nvs.driver_area.size)
return physical_nvs.memcpy_to_nvs(destination, source, size, with_checksum);
uint32_t dest = destination;
uint8_t checksum = with_checksum ? calc_checksum(source, size) : 0;
dirty = false;
for(; size > 0; size--)
ram_put_byte(dest++, *(source++));
if(with_checksum)
ram_put_byte(dest, checksum);
if(source == hal.nvs.driver_area.mem_address)
dirty = true;
if(dirty && physical_nvs.type != NVS_None) {
uint8_t idx = 0;
settings_dirty.is_dirty = true;
if(hal.nvs.driver_area.address && destination >= hal.nvs.driver_area.address)
settings_dirty.driver_settings = true;
else {
do {
if(target[idx].addr == destination)
break;
} while(target[++idx].addr);
if(target[idx].addr) switch(target[idx].type) {
case NVS_GROUP_GLOBAL:
settings_dirty.global_settings = true;
break;
#ifdef N_TOOLS
case NVS_GROUP_TOOLS:
settings_dirty.tool_data |= (1 << target[idx].offset);
break;
#endif
case NVS_GROUP_PARAMETERS:
settings_dirty.coord_data |= (1 << target[idx].offset);
break;
case NVS_GROUP_STARTUP:
settings_dirty.startup_lines |= (1 << target[idx].offset);
break;
case NVS_GROUP_BUILD:
settings_dirty.build_info = true;
break;
}
}
}
return NVS_TransferResult_OK;
}
static nvs_transfer_result_t memcpy_from_ram (uint8_t *destination, uint32_t source, uint32_t size, bool with_checksum)
{
if(hal.nvs.driver_area.address && source > hal.nvs.driver_area.address + hal.nvs.driver_area.size)
return physical_nvs.memcpy_from_nvs(destination, source, size, with_checksum);
uint8_t checksum = with_checksum ? calc_checksum(&nvsbuffer[source], size) : 0;
for(; size > 0; size--)
*(destination++) = ram_get_byte(source++);
return with_checksum ? (checksum == ram_get_byte(source) ? NVS_TransferResult_OK : NVS_TransferResult_Failed) : NVS_TransferResult_OK;
}
static void nvs_warning (sys_state_t state)
{
report_message("Not enough heap for NVS buffer!", Message_Warning);
}
// Try to allocate RAM from heap for buffer/emulation.
bool nvs_buffer_alloc (void)
{
assert(NVS_SIZE >= GRBL_NVS_SIZE);
nvsbuffer = malloc(NVS_SIZE);
return nvsbuffer != NULL;
}
//
// Switch over to RAM based copy.
// Changes to RAM based copy will be written to physical storage when Grbl is in IDLE state.
bool nvs_buffer_init (void)
{
if(nvsbuffer) {
memcpy(&physical_nvs, &hal.nvs, sizeof(nvs_io_t)); // save pointers to physical storage handler functions
// Copy physical storage content to RAM when available
if(physical_nvs.type == NVS_Flash)
physical_nvs.memcpy_from_flash(nvsbuffer);
else if(physical_nvs.type != NVS_None)
physical_nvs.memcpy_from_nvs(nvsbuffer, 0, GRBL_NVS_SIZE + hal.nvs.driver_area.size, false);
// Switch hal to use RAM version of non-volatile storage data
hal.nvs.type = NVS_Emulated;
hal.nvs.get_byte = &ram_get_byte;
hal.nvs.put_byte = &ram_put_byte;
hal.nvs.memcpy_to_nvs = &memcpy_to_ram;
hal.nvs.memcpy_from_nvs = &memcpy_from_ram;
hal.nvs.memcpy_from_flash = NULL;
hal.nvs.memcpy_to_flash = NULL;
// If no physical storage available or if NVS import fails copy default settings to RAM
// and write out to physical storage when available.
if(physical_nvs.type == NVS_None || ram_get_byte(0) != SETTINGS_VERSION) {
settings_restore(settings_all);
if(physical_nvs.type == NVS_Flash)
physical_nvs.memcpy_to_flash(nvsbuffer);
else if(physical_nvs.memcpy_to_nvs)
physical_nvs.memcpy_to_nvs(0, nvsbuffer, GRBL_NVS_SIZE + hal.nvs.driver_area.size, false);
if(physical_nvs.type != NVS_None)
grbl.report.status_message(Status_SettingReadFail);
}
} else
protocol_enqueue_rt_command(nvs_warning);
// Clear settings dirty flags
memset(&settings_dirty, 0, sizeof(settings_dirty_t));
return nvsbuffer != NULL;
}
// Allocate NVS block for driver settings.
// NOTE: allocation has to be done before content is copied from physical storage.
nvs_address_t nvs_alloc (size_t size)
{
static uint8_t *mem_address;
nvs_address_t addr = 0;
// Check if already switched to emulation or buffer allocation failed, return NULL if so.
if(hal.nvs.type == NVS_Emulated || nvsbuffer == NULL)
return 0;
if(hal.nvs.driver_area.address == 0) {
hal.nvs.driver_area.address = GRBL_NVS_SIZE;
hal.nvs.driver_area.mem_address = mem_address = nvsbuffer + GRBL_NVS_SIZE;
}
size += NVS_CRC_BYTES; // add room for checksum.
if(hal.nvs.driver_area.size + size < (NVS_SIZE - GRBL_NVS_SIZE)) {
mem_address = (uint8_t *)((uint32_t)(mem_address - 1) | 0x03) + 1; // Align to word boundary
addr = mem_address - nvsbuffer;
mem_address += size;
hal.nvs.driver_area.size = mem_address - hal.nvs.driver_area.mem_address;
hal.nvs.size = GRBL_NVS_SIZE + hal.nvs.driver_area.size + 1;
}
return addr;
}
// Write RAM changes to physical storage
void nvs_buffer_sync_physical (void)
{
if(!settings_dirty.is_dirty)
return;
if(physical_nvs.memcpy_to_nvs) {
if(settings_dirty.build_info)
settings_dirty.build_info = physical_nvs.memcpy_to_nvs(NVS_ADDR_BUILD_INFO, (uint8_t *)(nvsbuffer + NVS_ADDR_BUILD_INFO), sizeof(stored_line_t) + NVS_CRC_BYTES, false) != NVS_TransferResult_OK;
if(settings_dirty.global_settings)
settings_dirty.global_settings = physical_nvs.memcpy_to_nvs(NVS_ADDR_GLOBAL, (uint8_t *)(nvsbuffer + NVS_ADDR_GLOBAL), sizeof(settings_t) + NVS_CRC_BYTES, false) != NVS_TransferResult_OK;
uint_fast8_t idx = N_STARTUP_LINE, offset;
if(settings_dirty.startup_lines) do {
idx--;
if(bit_istrue(settings_dirty.startup_lines, bit(idx))) {
bit_false(settings_dirty.startup_lines, bit(idx));
offset = NVS_ADDR_STARTUP_BLOCK + idx * (sizeof(stored_line_t) + NVS_CRC_BYTES);
if(physical_nvs.memcpy_to_nvs(offset, (uint8_t *)(nvsbuffer + offset), sizeof(stored_line_t) + NVS_CRC_BYTES, false) == NVS_TransferResult_OK)
bit_false(settings_dirty.startup_lines, bit(idx));
}
} while(idx);
idx = N_CoordinateSystems;
if(settings_dirty.coord_data) do {
if(bit_istrue(settings_dirty.coord_data, bit(idx))) {
offset = NVS_ADDR_PARAMETERS + idx * (sizeof(coord_data_t) + NVS_CRC_BYTES);
if(physical_nvs.memcpy_to_nvs(offset, (uint8_t *)(nvsbuffer + offset), sizeof(coord_data_t) + NVS_CRC_BYTES, false) == NVS_TransferResult_OK)
bit_false(settings_dirty.coord_data, bit(idx));
}
} while(idx--);
if(settings_dirty.driver_settings) {
if(hal.nvs.driver_area.size > 0)
settings_dirty.driver_settings = physical_nvs.memcpy_to_nvs(hal.nvs.driver_area.address, (uint8_t *)(nvsbuffer + hal.nvs.driver_area.address), hal.nvs.driver_area.size, false) != NVS_TransferResult_OK;
else
settings_dirty.driver_settings = false;
}
#ifdef N_TOOLS
idx = N_TOOLS;
if(settings_dirty.tool_data) do {
idx--;
if(bit_istrue(settings_dirty.tool_data, bit(idx))) {
offset = NVS_ADDR_TOOL_TABLE + idx * (sizeof(tool_data_t) + NVS_CRC_BYTES);
if(physical_nvs.memcpy_to_nvs(offset, (uint8_t *)(nvsbuffer + offset), sizeof(tool_data_t) + NVS_CRC_BYTES, false) == NVS_TransferResult_OK)
bit_false(settings_dirty.tool_data, bit(idx));
}
} while(idx);
#endif
settings_dirty.is_dirty = settings_dirty.coord_data ||
settings_dirty.global_settings ||
settings_dirty.driver_settings ||
settings_dirty.startup_lines ||
#ifdef N_TOOLS
settings_dirty.tool_data ||
#endif
settings_dirty.build_info;
} else if(physical_nvs.memcpy_to_flash) {
physical_nvs.memcpy_to_flash(nvsbuffer);
settings_dirty.is_dirty = false;
}
}
nvs_io_t *nvs_buffer_get_physical (void)
{
return hal.nvs.type == NVS_Emulated ? &physical_nvs : &hal.nvs;
}
#ifndef DEBUGOUT
#include "report.h"
void nvs_memmap (void)
{
char buf[30];
report_message("NVS Area: addr size", Message_Plain);
strcpy(buf, "Global: ");
strcat(buf, uitoa(NVS_ADDR_GLOBAL));
strcat(buf, " ");
strcat(buf, uitoa(sizeof(settings_t) + NVS_CRC_BYTES));
report_message(buf, Message_Plain);
strcpy(buf, "Parameters: ");
strcat(buf, uitoa(NVS_ADDR_PARAMETERS));
strcat(buf, " ");
strcat(buf, uitoa(N_CoordinateSystems * (sizeof(coord_data_t) + NVS_CRC_BYTES)));
report_message(buf, Message_Plain);
strcpy(buf, "Startup block: ");
strcat(buf, uitoa(NVS_ADDR_STARTUP_BLOCK));
strcat(buf, " ");
strcat(buf, uitoa(N_STARTUP_LINE * (sizeof(stored_line_t) + NVS_CRC_BYTES)));
report_message(buf, Message_Plain);
strcpy(buf, "Build info: ");
strcat(buf, uitoa(NVS_ADDR_BUILD_INFO));
strcat(buf, " ");
strcat(buf, uitoa(sizeof(stored_line_t) + NVS_CRC_BYTES));
report_message(buf, Message_Plain);
strcpy(buf, "Driver: ");
strcat(buf, uitoa(hal.nvs.driver_area.address));
strcat(buf, " ");
strcat(buf, uitoa(hal.nvs.driver_area.size));
report_message(buf, Message_Plain);
}
#endif
+49
View File
@@ -0,0 +1,49 @@
/*
nvs_buffer.h - RAM based non-volatile storage buffer/emulation
Part of grblHAL
Copyright (c) 2017-2020 Terje Io
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _NVS_BUFFER_H_
#define _NVS_BUFFER_H_
typedef uint32_t nvs_address_t;
typedef struct {
bool is_dirty;
bool global_settings;
bool build_info;
bool driver_settings;
uint8_t startup_lines;
uint16_t coord_data;
#ifdef N_TOOLS
uint16_t tool_data;
#endif
} settings_dirty_t;
extern settings_dirty_t settings_dirty;
bool nvs_buffer_init (void);
bool nvs_buffer_alloc (void);
nvs_address_t nvs_alloc (size_t size);
void nvs_buffer_sync_physical (void);
nvs_io_t *nvs_buffer_get_physical (void);
void nvs_memmap (void);
#endif
+85
View File
@@ -0,0 +1,85 @@
/*
override.c - An embedded CNC Controller with rs274/ngc (g-code) support
Buffer handlers for real-time override commands
Part of grblHAL
Copyright (c) 2017-2019 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
#include "grbl.h"
#include "override.h"
typedef struct {
volatile uint_fast8_t head;
volatile uint_fast8_t tail;
uint8_t buf[OVERRIDE_BUFSIZE];
} override_queue_t;
static override_queue_t feed = {0}, accessory = {0};
ISR_CODE void enqueue_feed_override (uint8_t cmd)
{
uint_fast8_t bptr = (feed.head + 1) & (OVERRIDE_BUFSIZE - 1); // Get next head pointer
if(bptr != feed.tail) { // If not buffer full
feed.buf[feed.head] = cmd; // add data to buffer
feed.head = bptr; // and update pointer
}
}
// Returns 0 if no commands enqueued
uint8_t get_feed_override (void)
{
uint8_t data = 0;
uint_fast8_t bptr = feed.tail;
if(bptr != feed.head) {
data = feed.buf[bptr++]; // Get next character, increment tmp pointer
feed.tail = bptr & (OVERRIDE_BUFSIZE - 1); // and update pointer
}
return data;
}
ISR_CODE void enqueue_accessory_override (uint8_t cmd)
{
uint_fast8_t bptr = (accessory.head + 1) & (OVERRIDE_BUFSIZE - 1); // Get next head pointer
if(bptr != accessory.tail) { // If not buffer full
accessory.buf[accessory.head] = cmd; // add data to buffer
accessory.head = bptr; // and update pointer
}
}
// Returns 0 if no commands enqueued
uint8_t get_accessory_override (void)
{
uint8_t data = 0;
uint_fast8_t bptr = accessory.tail;
if(bptr != accessory.head) {
data = accessory.buf[bptr++]; // Get next character, increment tmp pointer
accessory.tail = bptr & (OVERRIDE_BUFSIZE - 1); // and update pointer
}
return data;
}
void flush_override_buffers () {
feed.head = feed.tail = accessory.head = accessory.tail = 0;
}
+37
View File
@@ -0,0 +1,37 @@
/*
override.h - An embedded CNC Controller with rs274/ngc (g-code) support
Buffer handlers for real-time override commands
Part of grblHAL
Copyright (c) 2016-2019 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _OVERRIDE_H_
#define _OVERRIDE_H_
#ifndef OVERRIDE_BUFSIZE
#define OVERRIDE_BUFSIZE 16 // must be a power of 2
#endif
void flush_override_buffers ();
void enqueue_feed_override (uint8_t cmd);
uint8_t get_feed_override (void);
void enqueue_accessory_override (uint8_t cmd);
uint8_t get_accessory_override (void);
#endif
+105
View File
@@ -0,0 +1,105 @@
/*
pid.c - An embedded CNC Controller with rs274/ngc (g-code) support
PID algorithm for closed loop control
NOTE: not referenced in the core grbl code
Part of grblHAL
Copyright (c) 2020-2021 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "pid.h"
// Fixed point version: TODO
// Float version
void pidf_init (pidf_t *pid, pid_values_t *config)
{
pidf_reset(pid);
memcpy(&pid->cfg, config, sizeof(pid_values_t));
}
bool pidf_config_changed (pidf_t *pid, pid_values_t *config)
{
return memcmp(&pid->cfg, config, sizeof(pid_values_t));
}
void pidf_reset (pidf_t *pid)
{
pid->error = 0.0f;
pid->i_error = 0.0f;
pid->d_error = 0.0f;
pid->sample_rate_prev = 1.0f;
}
float pidf (pidf_t *pid, float command, float actual, float sample_rate)
{
float error = command - actual;
/*
if(error > pid->deadband)
error -= pid->deadband;
else if (error < pid->deadband)
error += pid->deadband;
else
error = 0.0f;
*/
// calculate the proportional term
float pidres = pid->cfg.p_gain * error;
// calculate and add the integral term
pid->i_error += error * (pid->sample_rate_prev / sample_rate);
if(pid->cfg.i_max_error != 0.0f) {
if (pid->i_error > pid->cfg.i_max_error)
pid->i_error = pid->cfg.i_max_error;
else if (pid->i_error < -pid->cfg.i_max_error)
pid->i_error = -pid->cfg.i_max_error;
}
pidres += pid->cfg.i_gain * pid->i_error;
// calculate and add the derivative term
if(pid->cfg.d_gain != 0.0f) {
float p_error = (error - pid->d_error) * (sample_rate / pid->sample_rate_prev);
if(pid->cfg.d_max_error != 0.0f) {
if (p_error > pid->cfg.d_max_error)
p_error = pid->cfg.d_max_error;
else if (p_error < -pid->cfg.d_max_error)
p_error = -pid->cfg.d_max_error;
}
pidres += pid->cfg.d_gain * p_error;
pid->d_error = error;
}
pid->sample_rate_prev = sample_rate;
// limit error output
if(pid->cfg.max_error != 0.0f) {
if(pidres > pid->cfg.max_error)
pidres = pid->cfg.max_error;
else if(pidres < -pid->cfg.max_error)
pidres = -pid->cfg.max_error;
}
pid->error = pidres;
return pidres;
}
+48
View File
@@ -0,0 +1,48 @@
/*
pid.h - An embedded CNC Controller with rs274/ngc (g-code) support
PID algorithm for closed loop control
NOTE: not referenced in the core grbl code
Part of grblHAL
Copyright (c) 2020-2021 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _PID_H_
#define _PID_H_
#include <stdbool.h>
#include "settings.h"
typedef struct {
pid_values_t cfg;
float deadband;
float i_error;
float d_error;
float sample_rate_prev;
float error;
float max_error;
} pidf_t;
void pidf_reset (pidf_t *pid);
void pidf_init(pidf_t *pid, pid_values_t *config);
bool pidf_config_changed (pidf_t *pid, pid_values_t *config);
float pidf (pidf_t *pid, float command, float actual, float sample_rate);
#endif
+576
View File
File diff suppressed because it is too large Load Diff
+152
View File
@@ -0,0 +1,152 @@
/*
planner.h - buffers movement commands and manages the acceleration profile plan
Part of grblHAL
Copyright (c) 2019-2021 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _PLANNER_H_
#define _PLANNER_H_
// The number of linear motions that can be in the plan at any give time
#ifndef BLOCK_BUFFER_SIZE
#define BLOCK_BUFFER_SIZE 36
#endif
typedef union {
uint32_t value;
struct {
uint16_t rapid_motion :1,
system_motion :1,
jog_motion :1,
backlash_motion :1,
no_feed_override :1,
inverse_time :1,
is_rpm_rate_adjusted :1,
is_rpm_pos_adjusted :1,
is_laser_ppi_mode :1,
unassigned :7;
spindle_state_t spindle;
coolant_state_t coolant;
};
} planner_cond_t;
// This struct stores a linear movement of a g-code block motion with its critical "nominal" values
// are as specified in the source g-code.
typedef struct plan_block {
// Fields used by the bresenham algorithm for tracing the line
// NOTE: Used by stepper algorithm to execute the block correctly. Do not alter these values.
uint32_t steps[N_AXIS]; // Step count along each axis
uint32_t step_event_count; // The maximum step axis count and number of steps required to complete this block.
axes_signals_t direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
// Block condition data to ensure correct execution depending on states and overrides.
planner_cond_t condition; // Block bitfield variable defining block run conditions. Copied from pl_line_data.
gc_override_flags_t overrides; // Block bitfield variable for overrides
int32_t line_number; // Block line number for real-time reporting. Copied from pl_line_data.
// Fields used by the motion planner to manage acceleration. Some of these values may be updated
// by the stepper module during execution of special motion cases for replanning purposes.
float entry_speed_sqr; // The current planned entry speed at block junction in (mm/min)^2
float max_entry_speed_sqr; // Maximum allowable entry speed based on the minimum of junction limit and
// neighboring nominal speeds with overrides in (mm/min)^2
float acceleration; // Axis-limit adjusted line acceleration in (mm/min^2). Does not change.
float millimeters; // The remaining distance for this block to be executed in (mm).
// NOTE: This value may be altered by stepper algorithm during execution.
// Stored rate limiting data used by planner when changes occur.
float max_junction_speed_sqr; // Junction entry speed limit based on direction vectors in (mm/min)^2
float rapid_rate; // Axis-limit adjusted maximum rate for this block direction in (mm/min)
float programmed_rate; // Programmed rate of this block (mm/min).
// Stored spindle speed data used by spindle overrides and resuming methods.
spindle_t spindle; // Block spindle speed. Copied from pl_line_data.
char *message; // Message to be displayed when block is executed.
output_command_t *output_commands;
struct plan_block *prev, *next; // Linked list pointers, DO NOT MOVE - these MUST be the last elements in the struct!
} plan_block_t;
// Planner data prototype. Must be used when passing new motions to the planner.
typedef struct {
float feed_rate; // Desired feed rate for line motion. Value is ignored, if rapid motion.
spindle_t spindle; // Desired spindle speed through line motion.
planner_cond_t condition; // Bitfield variable to indicate planner conditions. See defines above.
gc_override_flags_t overrides; // Block bitfield variable for overrides
int32_t line_number; // Desired line number to report when executing.
// void *parameters; // TODO: pointer to extra parameters, for canned cycles and threading?
char *message; // Message to be displayed when block is executed.
output_command_t *output_commands;
} plan_line_data_t;
// Define planner variables
typedef struct {
int32_t position[N_AXIS]; // The planner position of the tool in absolute steps. Kept separate
// from g-code position for movements requiring multiple line motions,
// i.e. arcs, canned cycles, and backlash compensation.
float previous_unit_vec[N_AXIS]; // Unit vector of previous path line segment
float previous_nominal_speed; // Nominal speed of previous path line segment
} planner_t;
// Initialize and reset the motion plan subsystem
void plan_reset(); // Reset all
//void plan_reset_buffer(); // Reset buffer only.
// Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position
// in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed
// rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes.
bool plan_buffer_line(float *target, plan_line_data_t *pl_data);
// Called when the current block is no longer needed. Discards the block and makes the memory
// availible for new blocks.
void plan_discard_current_block();
// Gets the planner block for the special system motion cases. (Parking/Homing)
plan_block_t *plan_get_system_motion_block();
// Gets the current block. Returns NULL if buffer empty
plan_block_t *plan_get_current_block();
// Called by step segment buffer when computing executing block velocity profile.
float plan_get_exec_block_exit_speed_sqr();
// Called by main program during planner calculations and step segment buffer during initialization.
float plan_compute_profile_nominal_speed(plan_block_t *block);
// Re-calculates buffered motions profile parameters upon a motion-based override change.
void plan_update_velocity_profile_parameters();
// Reset the planner position vector (in steps)
void plan_sync_position();
// Reinitialize plan with a partially completed block
void plan_cycle_reinitialize();
// Returns the number of available blocks in the planner buffer.
uint_fast16_t plan_get_block_buffer_available();
// Returns the status of the block ring buffer. True, if buffer is full.
bool plan_check_full_buffer();
void plan_get_planner_mpos(float *target);
void plan_feed_override (uint_fast8_t feed_override, uint_fast8_t rapid_override);
#endif
+32
View File
@@ -0,0 +1,32 @@
/*
platform.h - platform specific definitions
Part of grblHAL
Copyright (c) 2021 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#if defined(STM32F103xB) || defined(STM32F401xC) || defined(STM32F407xx) || defined(STM32F411xE) || defined(STM32F446xx)
#define STM32_PLATFORM
#endif
#if defined(STM32_PLATFORM) || defined(__LPC17XX__) || defined(__IMXRT1062__)
#define UINT32FMT "lu"
#else
#define UINT32FMT "u"
#endif
+190
View File
@@ -0,0 +1,190 @@
/*
plugins.h - An embedded CNC Controller with rs274/ngc (g-code) support
Some data structures and function declarations for plugins that require driver code
These are NOT referenced in the core grbl code
Part of grblHAL
Copyright (c) 2020-2021 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _PLUGINS_H_
#define _PLUGINS_H_
#include <stdint.h>
#include <stdbool.h>
#include "nvs.h"
// Jogging
typedef struct {
float fast_speed;
float slow_speed;
float step_speed;
float fast_distance;
float slow_distance;
float step_distance;
} jog_settings_t;
// Networking
typedef enum {
IpMode_Static = 0,
IpMode_DHCP,
IpMode_AutoIP
} ip_mode_t;
typedef union {
uint8_t mask;
struct {
uint8_t telnet :1,
websocket :1,
http :1,
dns :1,
mdns :1,
ssdp :1,
webdav :1,
unassigned :1;
};
} network_services_t;
typedef char ssid_t[65];
typedef char password_t[33];
typedef char hostname_t[33];
typedef struct {
char ip[16];
char gateway[16];
char mask[16];
hostname_t hostname;
uint16_t telnet_port;
uint16_t websocket_port;
uint16_t http_port;
ip_mode_t ip_mode;
network_services_t services;
} network_settings_t;
typedef enum {
WiFiMode_NULL = 0,
WiFiMode_STA,
WiFiMode_AP,
WiFiMode_APSTA
} grbl_wifi_mode_t;
typedef struct {
ssid_t ssid;
password_t password;
char country[4];
uint8_t channel;
network_settings_t network;
} wifi_ap_settings_t;
typedef struct {
ssid_t ssid;
password_t password;
network_settings_t network;
} wifi_sta_settings_t;
typedef struct {
char device_name[33];
char service_name[33];
} bluetooth_settings_t;
typedef struct {
uint32_t baud_rate;
uint32_t rx_timeout;
} modbus_settings_t;
// Quadrature encoder interface
typedef enum {
Encoder_Universal = 0,
Encoder_FeedRate,
Encoder_RapidRate,
Encoder_Spindle_RPM,
Encoder_MPG,
Encoder_MPG_X,
Encoder_MPG_Y,
Encoder_MPG_Z,
Encoder_MPG_A,
Encoder_MPG_B,
Encoder_MPG_C,
Encoder_Spindle_Position
} encoder_mode_t;
typedef enum {
Setting_EncoderMode = 0,
Setting_EncoderCPR = 1, // Count Per Revolution
Setting_EncoderCPD = 2, // Count Per Detent
Setting_EncoderDblClickWindow = 3 // ms
} encoder_setting_id_t;
typedef union {
uint8_t events;
struct {
uint8_t position_changed :1,
click :1,
dbl_click :1,
long_click :1,
index_pulse :1;
};
} encoder_event_t;
typedef union {
uint8_t flags;
uint8_t value;
struct {
uint8_t single_count_per_detent :1;
};
} encoder_flags_t;
typedef struct {
encoder_mode_t mode;
uint32_t cpr; // count per revolution
uint32_t cpd; // count per detent
uint32_t dbl_click_window; // ms
encoder_flags_t flags;
} encoder_settings_t;
typedef struct {
encoder_mode_t mode;
uint_fast8_t id;
uint_fast8_t axis; // axis index for MPG encoders, 0xFF for others
int32_t position;
uint32_t velocity;
encoder_event_t event;
encoder_settings_t *settings;
} encoder_t;
// EEPROM/FRAM interface
typedef struct {
uint8_t address;
uint8_t word_addr_bytes;
uint16_t word_addr;
volatile uint_fast16_t count;
bool add_checksum;
uint8_t checksum;
uint8_t *data;
} nvs_transfer_t;
extern nvs_transfer_result_t i2c_nvs_transfer (nvs_transfer_t *i2c, bool read);
extern void my_plugin_init (void) __attribute__((weak));
#endif
+43
View File
@@ -0,0 +1,43 @@
/*
probe.h - An embedded CNC Controller with rs274/ngc (g-code) support
Part of grblHAL
Copyright (c) 2020 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _PROBE_H_
#define _PROBE_H_
// Values that define the probing state machine.
typedef enum {
Probing_Off = 0,
Probing_Active
} probing_state_t;
typedef union {
uint8_t value;
struct {
uint8_t triggered :1,
connected :1,
inverted :1, // For driver use
is_probing :1, // For driver use
unassigned :4;
};
} probe_state_t;
#endif
+930
View File
File diff suppressed because it is too large Load Diff
+56
View File
@@ -0,0 +1,56 @@
/*
protocol.h - controls Grbl execution protocol and procedures
Part of grblHAL
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _PROTOCOL_H_
#define _PROTOCOL_H_
// Line buffer size from the input stream to be executed.
// NOTE: Not a problem except for extreme cases, but the line buffer size can be too small
// and g-code blocks can get truncated. Officially, the g-code standards support up to 256
// characters. In future versions, this will be increased, when we know how much extra
// memory space we can invest into here or we re-write the g-code parser not to have this
// buffer.
#ifndef LINE_BUFFER_SIZE
#define LINE_BUFFER_SIZE 257 // 256 characters plus terminator
#endif
// Starts Grbl main loop. It handles all incoming characters from the input stream and executes
// them as they complete. It is also responsible for finishing the initialization procedures.
bool protocol_main_loop (void);
// Checks and executes a realtime command at various stop points in main program
bool protocol_execute_realtime (void);
bool protocol_exec_rt_system (void);
void protocol_execute_noop (uint_fast16_t state);
bool protocol_enqueue_rt_command (on_execute_realtime_ptr fn);
// Executes the auto cycle feature, if enabled.
void protocol_auto_cycle_start (void);
// Block until all buffered steps are executed
bool protocol_buffer_synchronize (void);
bool protocol_enqueue_realtime_command (char c);
bool protocol_enqueue_gcode (char *data);
void protocol_message (char *message);
#endif
+1869
View File
File diff suppressed because it is too large Load Diff
+103
View File
@@ -0,0 +1,103 @@
/*
report.h - reporting and messaging methods
Part of grblHAL
Copyright (c) 2018-2021 Terje Io
Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _REPORT_H_
#define _REPORT_H_
#include "system.h"
// Message types for uncoded messages
typedef enum {
Message_Plain = 0,
Message_Info,
Message_Warning
} message_type_t;
// Initialize reporting subsystem
void report_init (void);
void report_init_fns (void);
// Prints system status messages.
status_code_t report_status_message (status_code_t status_code);
// Prints system alarm messages.
alarm_code_t report_alarm_message (alarm_code_t alarm_code);
// Prints feedback message, typically from gcode.
void report_message (const char *msg, message_type_t type);
// Prints miscellaneous feedback messages.
message_code_t report_feedback_message (message_code_t message_code);
// Prints welcome message.
void report_init_message (void);
// Prints Grbl help.
status_code_t report_help (char *args, char *lcargs);
void report_grbl_help();
// Prints Grbl settings
void report_grbl_settings (bool all, void *data);
// Prints Grbl setting
status_code_t report_grbl_setting (setting_id_t id, void *data);
// Prints an echo of the pre-parsed line received right before execution.
void report_echo_line_received (char *line);
// Prints realtime status report.
void report_realtime_status (void);
// Prints recorded probe position.
void report_probe_parameters (void);
// Prints current tool offsets.
void report_tool_offsets (void);
// Prints Grbl NGC parameters (coordinate offsets, probe).
void report_ngc_parameters (void);
// Prints current g-code parser mode state.
void report_gcode_modes (void);
// Prints startup line when requested and executed.
void report_startup_line (uint8_t n, char *line);
void report_execute_startup_message (char *line, status_code_t status_code);
// Prints build info and user info.
void report_build_info (char *line, bool extended);
status_code_t report_alarm_details (void);
status_code_t report_error_details (void);
status_code_t report_setting_group_details (bool by_id, char *prefix);
status_code_t report_settings_details (bool human_readable, setting_id_t setting, setting_group_t group);
status_code_t report_last_signals_event (sys_state_t state, char *args);
status_code_t report_current_limit_state (sys_state_t state, char *args);
// Prints spindle data (encoder pulse and index count, angular position).
status_code_t report_spindle_data (sys_state_t state, char *args);
// Prints current PID log.
void report_pid_log (void);
#endif
+1807
View File
File diff suppressed because it is too large Load Diff
+721
View File
File diff suppressed because it is too large Load Diff
+88
View File
@@ -0,0 +1,88 @@
/*
sleep.c - determines and executes sleep procedures
Part of grblHAL
Copyright (c) 2018-2021 Terje Io
Copyright (c) 2016 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 <http://www.gnu.org/licenses/>.
*/
#include "hal.h"
#include "state_machine.h"
volatile bool slumber;
static void fall_asleep()
{
slumber = false;
}
// Starts sleep timer if running conditions are satified. When elapsed, sleep mode is executed.
static void sleep_execute()
{
// Enable sleep timeout
slumber = true;
hal.delay_ms((uint32_t)(SLEEP_DURATION * 1000.0f * 60.0f), fall_asleep);
// Fetch current number of buffered characters in input stream buffer.
uint16_t rx_initial = hal.stream.get_rx_buffer_available();
do {
// Monitor for any new input stream data or external events (queries, buttons, alarms) to exit.
if ((hal.stream.get_rx_buffer_available() != rx_initial) || sys.rt_exec_state || sys.rt_exec_alarm ) {
// Disable sleep timeout and return to normal operation.
hal.delay_ms(0, NULL);
return;
}
} while(slumber);
// If reached, sleep counter has expired. Execute sleep procedures.
// Notify user that Grbl has timed out and will be parking.
// To exit sleep, resume or reset. Either way, the job will not be recoverable.
grbl.report.feedback_message(Message_SleepMode);
system_set_exec_state_flag(EXEC_SLEEP);
}
// Checks running conditions for sleep. If satisfied, enables sleep timeout and executes
// sleep mode upon elapse.
// NOTE: Sleep procedures can be blocking, since Grbl isn't receiving any commands, nor moving.
// Hence, make sure any valid running state that executes the sleep timer is not one that is moving.
void sleep_check()
{
// The sleep execution feature will continue only if the machine is in an IDLE or HOLD state and
// has any powered components enabled.
// NOTE: With overrides or in laser mode, modal spindle and coolant state are not guaranteed. Need
// to directly monitor and record running state during parking to ensure proper function.
if (!sys.steppers_deenergize && (gc_state.modal.spindle.value || gc_state.modal.coolant.value)) {
switch(state_get()) {
case STATE_IDLE:
sleep_execute();
break;
case STATE_HOLD:
if(sys.holding_state == Hold_Complete)
sleep_execute();
break;
case STATE_SAFETY_DOOR:
if(sys.parking_state == Parking_DoorAjar)
sleep_execute();
break;
}
}
}
+29
View File
@@ -0,0 +1,29 @@
/*
sleep.h - Sleep methods header file
Part of grblHAL
Copyright (c) 2016 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 <http://www.gnu.org/licenses/>.
*/
#ifndef _SLEEP_H_
#define _SLEEP_H_
// Checks running conditions for sleep. If satisfied, enables sleep countdown and executes
// sleep mode upon elapse.
void sleep_check();
#endif
+225
View File
@@ -0,0 +1,225 @@
/*
spindle_control.c - spindle control methods
Part of grblHAL
Copyright (c) 2017-2021 Terje Io
Copyright (c) 2012-2015 Sungeun K. Jeon
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include "hal.h"
#include "protocol.h"
#include "state_machine.h"
// Set spindle speed override
// NOTE: Unlike motion overrides, spindle overrides do not require a planner reinitialization.
void spindle_set_override (uint_fast8_t speed_override)
{
if(sys.override.control.spindle_rpm_disable)
return;
speed_override = max(min(speed_override, MAX_SPINDLE_RPM_OVERRIDE), MIN_SPINDLE_RPM_OVERRIDE);
if ((uint8_t)speed_override != sys.override.spindle_rpm) {
sys.override.spindle_rpm = (uint8_t)speed_override;
if(state_get() == STATE_IDLE)
spindle_set_state(gc_state.modal.spindle, gc_state.spindle.rpm);
else
sys.step_control.update_spindle_rpm = On;
sys.report.overrides = On; // Set to report change immediately
}
}
// Immediately sets spindle running state with direction and spindle rpm, if enabled.
// Called by g-code parser spindle_sync(), parking retract and restore, g-code program end,
// sleep, and spindle stop override.
bool spindle_set_state (spindle_state_t state, float rpm)
{
if (!ABORTED) { // Block during abort.
if (!state.on) { // Halt or set spindle direction and rpm.
sys.spindle_rpm = rpm = 0.0f;
hal.spindle.set_state((spindle_state_t){0}, 0.0f);
} else {
// NOTE: Assumes all calls to this function is when Grbl is not moving or must remain off.
// TODO: alarm/interlock if going from CW to CCW directly in non-laser mode?
if (settings.mode == Mode_Laser && state.ccw)
rpm = 0.0f; // TODO: May need to be rpm_min*(100/MAX_SPINDLE_RPM_OVERRIDE);
hal.spindle.set_state(state, spindle_set_rpm(rpm, sys.override.spindle_rpm));
}
sys.report.spindle = On; // Set to report change immediately
st_rpm_changed(rpm);
}
return !ABORTED;
}
// G-code parser entry-point for setting spindle state. Forces a planner buffer sync and bails
// if an abort or check-mode is active.
bool spindle_sync (spindle_state_t state, float rpm)
{
bool ok = true;
bool at_speed = state_get() == STATE_CHECK_MODE || !state.on || !hal.driver_cap.spindle_at_speed || settings.spindle.at_speed_tolerance <= 0.0f;
if (state_get() != STATE_CHECK_MODE) {
// Empty planner buffer to ensure spindle is set when programmed.
if((ok = protocol_buffer_synchronize()) && spindle_set_state(state, rpm) && !at_speed) {
float delay = 0.0f;
while(!(at_speed = hal.spindle.get_state().at_speed)) {
delay_sec(0.1f, DelayMode_Dwell);
delay += 0.1f;
if(ABORTED)
break;
if(delay >= SAFETY_DOOR_SPINDLE_DELAY) {
system_raise_alarm(Alarm_Spindle);
break;
}
}
}
}
return ok && at_speed;
}
// Restore spindle running state with direction, enable, spindle RPM and appropriate delay.
bool spindle_restore (spindle_state_t state, float rpm)
{
bool ok = true;
if(settings.mode == Mode_Laser) // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts.
sys.step_control.update_spindle_rpm = On;
else { // TODO: add check for current spindle state matches restore state?
spindle_set_state(state, rpm);
if(state.on) {
if((ok = !hal.driver_cap.spindle_at_speed))
delay_sec(SAFETY_DOOR_SPINDLE_DELAY, DelayMode_SysSuspend);
else if((ok == (settings.spindle.at_speed_tolerance <= 0.0f))) {
float delay = 0.0f;
while(!(ok = hal.spindle.get_state().at_speed)) {
delay_sec(0.1f, DelayMode_SysSuspend);
delay += 0.1f;
if(ABORTED)
break;
if(delay >= SAFETY_DOOR_SPINDLE_DELAY) {
system_raise_alarm(Alarm_Spindle);
break;
}
}
}
}
}
return ok;
}
// Calculate and set programmed RPM according to override and max/min limits
float spindle_set_rpm (float rpm, uint8_t override_pct)
{
if(override_pct != 100)
rpm *= 0.01f * (float)override_pct; // Scale RPM by override value.
// Apply RPM limits
if (rpm <= 0.0f)
rpm = 0.0f;
else if (rpm > settings.spindle.rpm_max)
rpm = settings.spindle.rpm_max;
else if (rpm < settings.spindle.rpm_min)
rpm = settings.spindle.rpm_min;
sys.spindle_rpm = rpm;
return rpm;
}
//
// The following functions are not called by the core, may be called by driver code.
//
// calculate inverted pwm value if configured
static inline uint_fast16_t invert_pwm (spindle_pwm_t *pwm_data, uint_fast16_t pwm_value)
{
return pwm_data->invert_pwm ? pwm_data->period - pwm_value - 1 : pwm_value;
}
// Precompute PWM values for faster conversion.
// Returns false if no PWM range possible, driver should revert to simple on/off spindle control if so.
bool spindle_precompute_pwm_values (spindle_pwm_t *pwm_data, uint32_t clock_hz)
{
if(settings.spindle.rpm_max > settings.spindle.rpm_min) {
pwm_data->period = (uint_fast16_t)((float)clock_hz / settings.spindle.pwm_freq);
if(settings.spindle.pwm_off_value == 0.0f)
pwm_data->off_value = pwm_data->invert_pwm ? pwm_data->period : 0;
else
pwm_data->off_value = invert_pwm(pwm_data, (uint_fast16_t)(pwm_data->period * settings.spindle.pwm_off_value / 100.0f));
pwm_data->min_value = (uint_fast16_t)(pwm_data->period * settings.spindle.pwm_min_value / 100.0f);
pwm_data->max_value = (uint_fast16_t)(pwm_data->period * settings.spindle.pwm_max_value / 100.0f) + pwm_data->offset;
pwm_data->pwm_gradient = (float)(pwm_data->max_value - pwm_data->min_value) / (settings.spindle.rpm_max - settings.spindle.rpm_min);
pwm_data->always_on = settings.spindle.pwm_off_value != 0.0f;
}
#ifdef ENABLE_SPINDLE_LINEARIZATION
uint_fast8_t idx;
pwm_data->n_pieces = 0;
for(idx = 0; idx < SPINDLE_NPWM_PIECES; idx++) {
if(!isnan(settings.spindle.pwm_piece[idx].rpm) && settings.spindle.pwm_piece[idx].start != 0.0f)
memcpy(&pwm_data->piece[pwm_data->n_pieces++], &settings.spindle.pwm_piece[idx], sizeof(pwm_piece_t));
}
#endif
return settings.spindle.rpm_max > settings.spindle.rpm_min;
}
// Spindle RPM to PWM conversion.
uint_fast16_t spindle_compute_pwm_value (spindle_pwm_t *pwm_data, float rpm, bool pid_limit)
{
uint_fast16_t pwm_value;
if(rpm > settings.spindle.rpm_min) {
#ifdef ENABLE_SPINDLE_LINEARIZATION
// Compute intermediate PWM value with linear spindle speed model via piecewise linear fit model.
uint_fast8_t idx = pwm_data->n_pieces;
if(idx) {
do {
idx--;
if(idx == 0 || rpm > pwm_data->piece[idx].rpm) {
pwm_value = floorf(pwm_data->piece[idx].start * rpm - pwm_data->piece[idx].end);
break;
}
} while(idx);
} else
#endif
// Compute intermediate PWM value with linear spindle speed model.
pwm_value = (uint_fast16_t)floorf((rpm - settings.spindle.rpm_min) * pwm_data->pwm_gradient) + pwm_data->min_value;
if(pwm_value >= (pid_limit ? pwm_data->period : pwm_data->max_value))
pwm_value = pid_limit ? pwm_data->period - 1 : pwm_data->max_value;
else if(pwm_value < pwm_data->min_value)
pwm_value = pwm_data->min_value;
pwm_value = invert_pwm(pwm_data, pwm_value);
} else
pwm_value = rpm == 0.0f ? pwm_data->off_value : invert_pwm(pwm_data, pwm_data->min_value);
return pwm_value;
}
+109
View File
@@ -0,0 +1,109 @@
/*
spindle_control.h - spindle control methods
Part of grblHAL
Copyright (c) 2017-2021 Terje Io
Copyright (c) 2012-2015 Sungeun K. Jeon
Copyright (c) 2009-2011 Simen Svale Skogsrud
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _SPINDLE_CONTROL_H_
#define _SPINDLE_CONTROL_H_
typedef union {
uint8_t value;
uint8_t mask;
struct {
uint8_t on :1,
ccw :1,
pwm :1, // NOTE: only used for PWM inversion setting
reserved3 :1,
reserved4 :1,
encoder_error :1,
at_speed :1,
synchronized :1;
};
} spindle_state_t;
typedef struct {
float rpm;
float start;
float end;
} pwm_piece_t;
// Precalculated values that may be set/used by HAL driver to speed up RPM to PWM conversions if variable spindle is supported
typedef struct {
uint_fast16_t period;
uint_fast16_t off_value; // NOTE: this value holds the inverted version if software PWM inversion is enabled by the driver.
uint_fast16_t min_value;
uint_fast16_t max_value;
float pwm_gradient;
bool invert_pwm; // NOTE: set (by driver) when inversion is done in code
bool always_on;
int_fast16_t offset;
uint_fast16_t n_pieces;
pwm_piece_t piece[SPINDLE_NPWM_PIECES];
} spindle_pwm_t;
// Used when HAL driver supports spindle synchronization
typedef struct {
float rpm;
float rpm_low_limit;
float rpm_high_limit;
float angular_position; // Number of revolutions since last reset
float rpm_programmed;
uint32_t index_count;
uint32_t pulse_count;
uint32_t error_count;
spindle_state_t state_programmed;
} spindle_data_t;
typedef enum {
SpindleData_Counters,
SpindleData_RPM,
SpindleData_AngularPosition
} spindle_data_request_t;
void spindle_set_override (uint_fast8_t speed_override);
// Called by g-code parser when setting spindle state and requires a buffer sync.
// Immediately sets spindle running state with direction and spindle RPM, if enabled.
// Called by spindle_sync() after sync and parking motion/spindle stop override during restore.
// Called by g-code parser when setting spindle state and requires a buffer sync.
bool spindle_sync (spindle_state_t state, float rpm);
// Sets spindle running state with direction, enable, and spindle RPM.
bool spindle_set_state (spindle_state_t state, float rpm);
// Spindle speed calculation and limit handling
float spindle_set_rpm (float rpm, uint8_t speed_override);
// Restore spindle running state with direction, enable, spindle RPM and appropriate delay.
bool spindle_restore (spindle_state_t state, float rpm);
//
// The following functions are not called by the core, may be called by driver code.
//
// Precompute PWM values for faster conversion.
bool spindle_precompute_pwm_values (spindle_pwm_t *pwm_data, uint32_t clock_hz);
// Spindle speed to PWM conversion.
uint_fast16_t spindle_compute_pwm_value (spindle_pwm_t *pwm_data, float rpm, bool pid_limit);
#endif
+78
View File
@@ -0,0 +1,78 @@
/*
spindle_sync.h - An embedded CNC Controller with rs274/ngc (g-code) support
Spindle sync data strucures
NOTE: not referenced in the core grbl code
Part of grblHAL
Copyright (c) 2020-2021 Terje Io
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _SPINDLE_SYNC_H_
#define _SPINDLE_SYNC_H_
#include "pid.h"
// Free running timer log data.
// The free running timer is used to timestamp pulse events from the encoder.
typedef struct {
volatile uint32_t last_index; // Timer value at last encoder index pulse
volatile uint32_t last_pulse; // Timer value at last encoder pulse
volatile uint32_t pulse_length; // Last timer tics between spindle encoder pulse interrupts.
} spindle_encoder_timer_t;
// Pulse counter timer log data.
// This counter is used to "prescale" the encoder pulses in order to
// reduce pulse interrupt frequency. This allows the use of high PPR encoders
// without overloading the MCU while still making use of the better resolution.
// NOTE: if a 16bit counter is used then it is important than proper casting
// is performed in order to handle counter overflow correctly.
typedef struct {
volatile uint32_t last_count; // Counter value at last encoder pulse interrupt
volatile uint32_t last_index; // Counter value at last encoder index interrupt
volatile uint32_t index_count;
volatile uint32_t pulse_count;
} spindle_encoder_counter_t;
typedef struct {
uint32_t ppr; // Encoder pulses per revolution
float rpm_factor; // Inverse of event timer tics per RPM
float pulse_distance; // Encoder pulse distance in fraction of one revolution
uint32_t maximum_tt; // Maximum timer tics since last spindle encoder pulse before RPM = 0 is returned
spindle_encoder_timer_t timer; // Event timestamps
spindle_encoder_counter_t counter; // Encoder event counts
uint32_t error_count; // Incremented when actual PPR count differs from ppr setting
uint32_t tics_per_irq; // Counts per interrupt generated (prescaler value)
volatile bool spin_lock;
} spindle_encoder_t;
typedef struct {
float prev_pos; // Target position of previous segment
float steps_per_mm; // Steps per mm for current block
float programmed_rate; // Programmed feed in mm/rev for current block
int32_t min_cycles_per_tick; // Minimum cycles per tick for PID loop
uint_fast8_t segment_id; // Used for detecing start of new segment
pidf_t pid; // PID data for position
stepper_pulse_start_ptr stepper_pulse_start_normal; // Driver pulse function to restore after spindle sync move is completed
#ifdef PID_LOG
int32_t log[PID_LOG];
int32_t pos[PID_LOG];
#endif
} spindle_sync_t;
#endif

Some files were not shown because too many files have changed in this diff Show More