mirror of
https://github.com/grblHAL/core.git
synced 2026-09-22 03:08:33 +08:00
test check in
This commit is contained in:
@@ -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
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+56
@@ -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
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+721
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user