diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..97d41b66 --- /dev/null +++ b/.clang-format @@ -0,0 +1,92 @@ +--- +AccessModifierOffset: '-4' +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: 'true' +AlignConsecutiveDeclarations: 'true' +AlignEscapedNewlines: Right +AlignOperands: 'true' +AlignTrailingComments: 'true' +AllowShortBlocksOnASingleLine: 'true' +AllowShortCaseLabelsOnASingleLine: 'true' +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: 'false' +AllowShortLoopsOnASingleLine: 'false' +AlwaysBreakBeforeMultilineStrings: 'false' +AlwaysBreakTemplateDeclarations: 'true' +BinPackArguments: 'false' +BinPackParameters: 'false' +BreakBeforeBinaryOperators: None +BraceWrapping: + AfterClass: 'true' + AfterControlStatement: 'true' + AfterEnum: 'true' + AfterFunction: 'true' + AfterNamespace: 'true' + AfterObjCDeclaration: 'true' + AfterStruct: 'true' + AfterUnion: 'true' + AfterExternBlock: 'true' + BeforeCatch: 'true' + BeforeElse: 'true' + SplitEmptyFunction: 'false' + SplitEmptyRecord: 'false' + SplitEmptyNamespace: 'false' +BreakBeforeInheritanceComma: 'true' +BreakBeforeTernaryOperators: 'false' +BreakConstructorInitializers: AfterColon +BreakInheritanceList: AfterColon +ColumnLimit: '140' +CommentPragmas: '^ :: ' +CompactNamespaces: 'false' +Cpp11BracedListStyle: 'false' +FixNamespaceComments: 'false' +IncludeCategories: + - Regex: '^".*' + Priority: 1 + - Regex: '^"(.*)/' + Priority: 2 + - Regex: '^<(.*)/' + Priority: 3 + - Regex: '.*' + Priority: 4 +IncludeBlocks: Regroup +IndentCaseLabels: 'true' +IndentPPDirectives: AfterHash +IndentWidth: '4' +IndentWrappedFunctionNames: 'true' +JavaScriptQuotes: Leave +KeepEmptyLinesAtTheStartOfBlocks: 'false' +Language: Cpp +MaxEmptyLinesToKeep: '1' +NamespaceIndentation: All +PenaltyBreakBeforeFirstCallParameter: 7 +PenaltyBreakAssignment: 8 +PenaltyBreakComment: 200 +PenaltyBreakFirstLessLess: 50 +PenaltyBreakString: 100 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 10 +PenaltyReturnTypeOnItsOwnLine: 1000000 +PointerAlignment: Left +ReflowComments: 'false' +SortIncludes: 'false' +SortUsingDeclarations: 'true' +SpaceAfterTemplateKeyword: 'true' +SpaceBeforeAssignmentOperators: 'true' +SpaceBeforeCpp11BracedList: 'true' +SpaceBeforeCtorInitializerColon: 'true' +SpaceBeforeInheritanceColon: 'true' +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: 'true' +SpaceInEmptyParentheses: 'false' +SpacesBeforeTrailingComments: '2' +SpacesInAngles: 'false' +SpacesInCStyleCastParentheses: 'false' +SpacesInContainerLiterals: 'false' +SpacesInParentheses: 'false' +SpacesInSquareBrackets: 'false' +Standard: Cpp11 +TabWidth: '4' +UseTab: Never + +... diff --git a/CodingStyle.md b/CodingStyle.md new file mode 100644 index 00000000..70879e22 --- /dev/null +++ b/CodingStyle.md @@ -0,0 +1,80 @@ +# Coding style guidelines + +While most software developers have a strong opinion about coding +style and conventions, the general agreement is that having a single +coding style in your project is beneficial for the readability and +maintainability. + +Coding style of this project is enforced through `.clang-format`. +Most IDE's nowadays pick up the clang-format file automatically. If +this is not the case, please run it manually before committing code. + +Note that different IDE's are compiled against different versions of +clang-format. This clang-format file is created in such a way, that +it should work with most IDE's out-of-the-box, and can apply changes +when the file is saved. + +There may be violations of these guidelines in the code, due to +historical reasons or, in rare instances, other considerations. +We intend to fix such violations; patches that correct them +are most welcome - but should be tested carefully across the +supported compilation environments (Arduino and platformio). + +## Guidelines + +A few guidelines need to be taken into consideration while using +clang-format: + +1. Include order and `".."` vs `<...>` matters. Clang-format + automatically re-orders your include files. This configuration + is created in such a way that header file includes always add + the minimum number of implicit dependencies. If this generates + problems, you should be fixing your includes, instead of disabling + clang-format. +2. Preprocessor commands are not formatted nicely in some cases. + This can hurt readibility in rare cases, in which case it's + okay to disable clang-format temporarily with + `// clang-format off` and `// clang-format on`. Most notably, + machine definitions should have clang-format off. +3. Use `#pragma once` in all header files. The reason is that + preprocessor `#ifdef`s are nested automatically, which making + things messy when using the alternative. + +## Classes and namespaces + +Filenames should correspond with clas names, folder names should +correspond with namespace names. This implies that a file should +have a single class. + +## Naming + +- Class names and namespace names are named `CamelCase`. Note that + class and namespace names should only start with an `_` if they are + (A) not in the global namespace and (b) should otherwise start with a digit. + For example `_10VSpindle`. +- Class member functions should be `snake_case` +- Class member variables should be `_snake_case` with a leading `_`. + +Namespaces should have classes, and classes should have members. Avoid +using functions that have no class attached to them. + +## Using namespace + +- `using namespace` is not allowed in header files, except when + using it in the body of a function. +- Try to be conservative with `using namespace` in cpp files. + Prefer to use it in a function body whenever possible for clarity + what is used where. + +## Including files + +- It's a good practice to include just what you need. In general, + try to include as much as possible in the cpp file, and as little + as possible in the header file. +- A CPP file should normally include the corresponding header file + first (e.g. `WebSettings.cpp` should include `WebSettings.h`) + and then everything else. +- When including a system or library file, use `<...>` syntax; + when including a local file, use `"..."` syntax. Some IDE's + actually have trouble compiling if not done correctly. +- Never include a cpp file; always header files! diff --git a/Grbl_Esp32/BTconfig.cpp b/Grbl_Esp32/BTconfig.cpp index f761e552..49c081c3 100644 --- a/Grbl_Esp32/BTconfig.cpp +++ b/Grbl_Esp32/BTconfig.cpp @@ -18,29 +18,26 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef ARDUINO_ARCH_ESP32 - #include "grbl.h" #ifdef ENABLE_BLUETOOTH -#include "BluetoothSerial.h" -#include "BTconfig.h" +# include "BluetoothSerial.h" +# include "BTconfig.h" -BTConfig bt_config; +BTConfig bt_config; BluetoothSerial SerialBT; -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#endif +# endif const uint8_t* esp_bt_dev_get_address(void); -#ifdef __cplusplus +# ifdef __cplusplus } -#endif +# endif -String BTConfig::_btname = ""; +String BTConfig::_btname = ""; String BTConfig::_btclient = ""; -BTConfig::BTConfig() { -} +BTConfig::BTConfig() {} BTConfig::~BTConfig() { end(); @@ -48,27 +45,25 @@ BTConfig::~BTConfig() { static void my_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t* param) { switch (event) { - case ESP_SPP_SRV_OPEN_EVT: { //Server connection open - char str[18]; - str[17] = '\0'; - uint8_t* addr = param->srv_open.rem_bda; - sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - BTConfig::_btclient = str; - grbl_sendf(CLIENT_ALL, "[MSG:BT Connected with %s]\r\n", str); - } - break; - case ESP_SPP_CLOSE_EVT://Client connection closed - grbl_send(CLIENT_ALL, "[MSG:BT Disconnected]\r\n"); - BTConfig::_btclient = ""; - break; - default: - break; + case ESP_SPP_SRV_OPEN_EVT: { //Server connection open + char str[18]; + str[17] = '\0'; + uint8_t* addr = param->srv_open.rem_bda; + sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + BTConfig::_btclient = str; + grbl_sendf(CLIENT_ALL, "[MSG:BT Connected with %s]\r\n", str); + } break; + case ESP_SPP_CLOSE_EVT: //Client connection closed + grbl_send(CLIENT_ALL, "[MSG:BT Disconnected]\r\n"); + BTConfig::_btclient = ""; + break; + default: break; } } const char* BTConfig::info() { static String result; - String tmp; + String tmp; result = "[MSG:"; if (Is_BT_on()) { result += "Mode=BT:Name="; @@ -78,8 +73,10 @@ const char* BTConfig::info() { result += "):Status="; if (SerialBT.hasClient()) result += "Connected with " + _btclient; - else result += "Not connected"; - } else result += "No BT"; + else + result += "Not connected"; + } else + result += "No BT"; result += "]\r\n"; return result.c_str(); } @@ -102,7 +99,7 @@ bool BTConfig::isBTnameValid(const char* hostname) { const char* BTConfig::device_address() { const uint8_t* point = esp_bt_dev_get_address(); - static char str[18]; + static char str[18]; str[17] = '\0'; sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", (int)point[0], (int)point[1], (int)point[2], (int)point[3], (int)point[4], (int)point[5]); return str; @@ -122,7 +119,8 @@ void BTConfig::begin() { SerialBT.register_callback(&my_spp_cb); grbl_sendf(CLIENT_ALL, "[MSG:BT Started with %s]\r\n", _btname.c_str()); } - } else end(); + } else + end(); } /** @@ -156,7 +154,4 @@ void BTConfig::handle() { COMMANDS::wait(0); } - -#endif // ENABLE_BLUETOOTH - -#endif // ARDUINO_ARCH_ESP32 +#endif // ENABLE_BLUETOOTH diff --git a/Grbl_Esp32/BTconfig.h b/Grbl_Esp32/BTconfig.h index 8698ac0d..6807436c 100644 --- a/Grbl_Esp32/BTconfig.h +++ b/Grbl_Esp32/BTconfig.h @@ -20,40 +20,39 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED) - #error Bluetooth is not enabled! Please run `make menuconfig` to and enable it +# error Bluetooth is not enabled! Please run `make menuconfig` to and enable it #endif //defaults values #define DEFAULT_BT_NAME "btgrblesp" - //boundaries -#define MAX_BTNAME_LENGTH 32 -#define MIN_BTNAME_LENGTH 1 +#define MAX_BTNAME_LENGTH 32 +#define MIN_BTNAME_LENGTH 1 #define BT_EVENT_DISCONNECTED 0 #define BT_EVENT_CONNECTED 1 - #include "BluetoothSerial.h" extern BluetoothSerial SerialBT; class BTConfig { - public: +public: BTConfig(); ~BTConfig(); static const char* info(); - static void BTEvent(uint8_t event); - static bool isBTnameValid(const char* hostname); - static String BTname() {return _btname;} + static void BTEvent(uint8_t event); + static bool isBTnameValid(const char* hostname); + static String BTname() { return _btname; } static const char* device_address(); - static void begin(); - static void end(); - static void handle(); - static void reset_settings(); - static bool Is_BT_on(); - static String _btclient; - private : + static void begin(); + static void end(); + static void handle(); + static void reset_settings(); + static bool Is_BT_on(); + static String _btclient; + +private: static String _btname; }; diff --git a/Grbl_Esp32/Custom/atari_1020.cpp b/Grbl_Esp32/Custom/atari_1020.cpp index b111a20f..427560d8 100644 --- a/Grbl_Esp32/Custom/atari_1020.cpp +++ b/Grbl_Esp32/Custom/atari_1020.cpp @@ -28,60 +28,60 @@ // in Machines/atari_1020.h, thus causing this file to be included // from ../custom_code.cpp -#define HOMING_PHASE_FULL_APPROACH 0 // move to right end -#define HOMING_PHASE_CHECK 1 // check reed switch -#define HOMING_PHASE_RETRACT 2 // retract -#define HOMING_PHASE_SHORT_APPROACH 3 // retract +#define HOMING_PHASE_FULL_APPROACH 0 // move to right end +#define HOMING_PHASE_CHECK 1 // check reed switch +#define HOMING_PHASE_RETRACT 2 // retract +#define HOMING_PHASE_SHORT_APPROACH 3 // retract static TaskHandle_t solenoidSyncTaskHandle = 0; -static TaskHandle_t atariHomingTaskHandle = 0; -int8_t solenoid_pwm_chan_num; -uint16_t solenoid_pull_count; -bool atari_homing = false; -uint8_t homing_phase = HOMING_PHASE_FULL_APPROACH; -uint8_t current_tool; +static TaskHandle_t atariHomingTaskHandle = 0; +int8_t solenoid_pwm_chan_num; +uint16_t solenoid_pull_count; +bool atari_homing = false; +uint8_t homing_phase = HOMING_PHASE_FULL_APPROACH; +uint8_t current_tool; void machine_init() { - solenoid_pull_count = 0; // initialize + solenoid_pull_count = 0; // initialize grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Atari 1020 Solenoid"); // setup PWM channel solenoid_pwm_chan_num = sys_get_next_PWM_chan_num(); ledcSetup(solenoid_pwm_chan_num, SOLENOID_PWM_FREQ, SOLENOID_PWM_RES_BITS); ledcAttachPin(SOLENOID_PEN_PIN, solenoid_pwm_chan_num); - pinMode(SOLENOID_DIRECTION_PIN, OUTPUT); // this sets the direction of the solenoid current - pinMode(REED_SW_PIN, INPUT_PULLUP); // external pullup required + pinMode(SOLENOID_DIRECTION_PIN, OUTPUT); // this sets the direction of the solenoid current + pinMode(REED_SW_PIN, INPUT_PULLUP); // external pullup required // setup a task that will calculate solenoid position - xTaskCreatePinnedToCore(solenoidSyncTask, // task - "solenoidSyncTask", // name for task - 4096, // size of task stack - NULL, // parameters - 1, // priority + xTaskCreatePinnedToCore(solenoidSyncTask, // task + "solenoidSyncTask", // name for task + 4096, // size of task stack + NULL, // parameters + 1, // priority &solenoidSyncTaskHandle, - 0 // core - ); + 0 // core + ); // setup a task that will do the custom homing sequence - xTaskCreatePinnedToCore(atari_home_task, // task - "atari_home_task", // name for task - 4096, // size of task stack - NULL, // parameters - 1, // priority + xTaskCreatePinnedToCore(atari_home_task, // task + "atari_home_task", // name for task + 4096, // size of task stack + NULL, // parameters + 1, // priority &atariHomingTaskHandle, - 0 // core - ); + 0 // core + ); } // this task tracks the Z position and sets the solenoid void solenoidSyncTask(void* pvParameters) { - int32_t current_position[N_AXIS]; // copy of current location - float m_pos[N_AXIS]; // machine position in mm - TickType_t xLastWakeTime; - const TickType_t xSolenoidFrequency = SOLENOID_TASK_FREQ; // in ticks (typically ms) - xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time. + int32_t current_position[N_AXIS]; // copy of current location + float m_pos[N_AXIS]; // machine position in mm + TickType_t xLastWakeTime; + const TickType_t xSolenoidFrequency = SOLENOID_TASK_FREQ; // in ticks (typically ms) + xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time. while (true) { // don't ever return from this or the task dies - memcpy(current_position, sys_position, sizeof(sys_position)); // get current position in step - system_convert_array_steps_to_mpos(m_pos, current_position); // convert to millimeters - calc_solenoid(m_pos[Z_AXIS]); // calculate kinematics and move the servos + memcpy(current_position, sys_position, sizeof(sys_position)); // get current position in step + system_convert_array_steps_to_mpos(m_pos, current_position); // convert to millimeters + calc_solenoid(m_pos[Z_AXIS]); // calculate kinematics and move the servos vTaskDelayUntil(&xLastWakeTime, xSolenoidFrequency); } } @@ -94,7 +94,7 @@ bool user_defined_homing() { // create and start a task to do the special homing homing_phase = HOMING_PHASE_FULL_APPROACH; atari_homing = true; - return true; // this does it...skip the rest of mc_homing_cycle(...) + return true; // this does it...skip the rest of mc_homing_cycle(...) } /* @@ -113,54 +113,54 @@ bool user_defined_homing() { */ void atari_home_task(void* pvParameters) { - uint8_t homing_attempt = 0; // how many times have we tried to home - TickType_t xLastWakeTime; - const TickType_t xHomingTaskFrequency = 100; // in ticks (typically ms) .... need to make sure there is enough time to get out of idle - char gcode_line[20]; + uint8_t homing_attempt = 0; // how many times have we tried to home + TickType_t xLastWakeTime; + const TickType_t xHomingTaskFrequency = 100; // in ticks (typically ms) .... need to make sure there is enough time to get out of idle + char gcode_line[20]; while (true) { // this task will only last as long as it is homing if (atari_homing) { // must be in idle or alarm state if (sys.state == STATE_IDLE) { switch (homing_phase) { - case HOMING_PHASE_FULL_APPROACH: // a full width move to insure it hits left end - inputBuffer.push("G90G0Z1\r"); // lift the pen - sprintf(gcode_line, "G91G0X%3.2f\r", -ATARI_PAPER_WIDTH + ATARI_HOME_POS - 3.0); // plus a little extra - inputBuffer.push(gcode_line); - homing_attempt = 1; - homing_phase = HOMING_PHASE_CHECK; - break; - case HOMING_PHASE_CHECK: // check the limits switch - if (digitalRead(REED_SW_PIN) == 0) { - // see if reed switch is grounded - inputBuffer.push("G4P0.1\n"); // dramtic pause - sys_position[X_AXIS] = ATARI_HOME_POS * axis_settings[X_AXIS]->steps_per_mm->get(); - sys_position[Y_AXIS] = 0.0; - sys_position[Z_AXIS] = 1.0 * axis_settings[Y_AXIS]->steps_per_mm->get(); - gc_sync_position(); - plan_sync_position(); - sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); // alway return to right side to reduce home travel stalls + case HOMING_PHASE_FULL_APPROACH: // a full width move to insure it hits left end + inputBuffer.push("G90G0Z1\r"); // lift the pen + sprintf(gcode_line, "G91G0X%3.2f\r", -ATARI_PAPER_WIDTH + ATARI_HOME_POS - 3.0); // plus a little extra inputBuffer.push(gcode_line); - current_tool = 1; // local copy for reference...until actual M6 change - gc_state.tool = current_tool; - atari_homing = false; // done with homing sequence - } else { - homing_phase = HOMING_PHASE_RETRACT; - homing_attempt++; - } - break; - case HOMING_PHASE_RETRACT: - sprintf(gcode_line, "G0X%3.2f\r", -ATARI_HOME_POS); - inputBuffer.push(gcode_line); - sprintf(gcode_line, "G0X%3.2f\r", ATARI_HOME_POS); - inputBuffer.push(gcode_line); - homing_phase = HOMING_PHASE_CHECK; - break; - default: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Homing phase error %d", homing_phase); - atari_homing = false; - ; // kills task - break; + homing_attempt = 1; + homing_phase = HOMING_PHASE_CHECK; + break; + case HOMING_PHASE_CHECK: // check the limits switch + if (digitalRead(REED_SW_PIN) == 0) { + // see if reed switch is grounded + inputBuffer.push("G4P0.1\n"); // dramtic pause + sys_position[X_AXIS] = ATARI_HOME_POS * axis_settings[X_AXIS]->steps_per_mm->get(); + sys_position[Y_AXIS] = 0.0; + sys_position[Z_AXIS] = 1.0 * axis_settings[Y_AXIS]->steps_per_mm->get(); + gc_sync_position(); + plan_sync_position(); + sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); // alway return to right side to reduce home travel stalls + inputBuffer.push(gcode_line); + current_tool = 1; // local copy for reference...until actual M6 change + gc_state.tool = current_tool; + atari_homing = false; // done with homing sequence + } else { + homing_phase = HOMING_PHASE_RETRACT; + homing_attempt++; + } + break; + case HOMING_PHASE_RETRACT: + sprintf(gcode_line, "G0X%3.2f\r", -ATARI_HOME_POS); + inputBuffer.push(gcode_line); + sprintf(gcode_line, "G0X%3.2f\r", ATARI_HOME_POS); + inputBuffer.push(gcode_line); + homing_phase = HOMING_PHASE_CHECK; + break; + default: + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Homing phase error %d", homing_phase); + atari_homing = false; + ; // kills task + break; } if (homing_attempt > ATARI_HOMING_ATTEMPTS) { // try all positions plus 1 @@ -177,25 +177,25 @@ void atari_home_task(void* pvParameters) { // calculate and set the PWM value for the servo void calc_solenoid(float penZ) { - bool isPenUp; + bool isPenUp; static bool previousPenState = false; - uint32_t solenoid_pen_pulse_len; // duty cycle of solenoid - isPenUp = ((penZ > 0) || (sys.state == STATE_ALARM)); // is pen above Z0 or is there an alarm + uint32_t solenoid_pen_pulse_len; // duty cycle of solenoid + isPenUp = ((penZ > 0) || (sys.state == STATE_ALARM)); // is pen above Z0 or is there an alarm // if the state has not change, we only count down to the pull time if (previousPenState == isPenUp) { // if state is unchanged if (solenoid_pull_count > 0) { solenoid_pull_count--; - solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_PULL; // stay at full power while counting down + solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_PULL; // stay at full power while counting down } else { - solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_HOLD; // pull in delay has expired so lower duty cycle + solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_HOLD; // pull in delay has expired so lower duty cycle } } else { // pen direction has changed - solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_PULL; // go to full power - solenoid_pull_count = SOLENOID_PULL_DURATION; // set the time to count down + solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_PULL; // go to full power + solenoid_pull_count = SOLENOID_PULL_DURATION; // set the time to count down } - previousPenState = isPenUp; // save the prev state + previousPenState = isPenUp; // save the prev state digitalWrite(SOLENOID_DIRECTION_PIN, isPenUp); // skip setting value if it is unchanged if (ledcRead(solenoid_pwm_chan_num) == solenoid_pen_pulse_len) @@ -214,8 +214,8 @@ void calc_solenoid(float penZ) { */ void user_tool_change(uint8_t new_tool) { uint8_t move_count; - char gcode_line[20]; - protocol_buffer_synchronize(); // wait for all previous moves to complete + char gcode_line[20]; + protocol_buffer_synchronize(); // wait for all previous moves to complete if ((new_tool < 1) || (new_tool > MAX_PEN_NUMBER)) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Requested Pen#%d is out of 1-4 range", new_tool); return; @@ -226,10 +226,10 @@ void user_tool_change(uint8_t new_tool) { move_count = BUMPS_PER_PEN_CHANGE * (new_tool - current_tool); else move_count = BUMPS_PER_PEN_CHANGE * ((MAX_PEN_NUMBER - current_tool) + new_tool); - sprintf(gcode_line, "G0Z%3.2f\r", ATARI_TOOL_CHANGE_Z); // go to tool change height + sprintf(gcode_line, "G0Z%3.2f\r", ATARI_TOOL_CHANGE_Z); // go to tool change height inputBuffer.push(gcode_line); for (uint8_t i = 0; i < move_count; i++) { - sprintf(gcode_line, "G0X%3.2f\r", ATARI_HOME_POS); // + sprintf(gcode_line, "G0X%3.2f\r", ATARI_HOME_POS); // inputBuffer.push(gcode_line); inputBuffer.push("G0X0\r"); } @@ -251,38 +251,36 @@ void user_defined_macro(uint8_t index) { char gcode_line[20]; switch (index) { #ifdef MACRO_BUTTON_0_PIN - case CONTROL_PIN_INDEX_MACRO_0: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Pen switch"); - inputBuffer.push("$H\r"); - break; + case CONTROL_PIN_INDEX_MACRO_0: + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Pen switch"); + inputBuffer.push("$H\r"); + break; #endif #ifdef MACRO_BUTTON_1_PIN - case CONTROL_PIN_INDEX_MACRO_1: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Color switch"); - atari_next_pen(); - sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); // alway return to right side to reduce home travel stalls - inputBuffer.push(gcode_line); - break; + case CONTROL_PIN_INDEX_MACRO_1: + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Color switch"); + atari_next_pen(); + sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); // alway return to right side to reduce home travel stalls + inputBuffer.push(gcode_line); + break; #endif #ifdef MACRO_BUTTON_2_PIN - case CONTROL_PIN_INDEX_MACRO_2: - // feed out some paper and reset the Y 0 - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Paper switch"); - inputBuffer.push("G0Y-25\r"); - inputBuffer.push("G4P0.1\r"); // sync...forces wait for planner to clear - sys_position[Y_AXIS] = 0.0; // reset the Y position - gc_sync_position(); - plan_sync_position(); - break; + case CONTROL_PIN_INDEX_MACRO_2: + // feed out some paper and reset the Y 0 + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Paper switch"); + inputBuffer.push("G0Y-25\r"); + inputBuffer.push("G4P0.1\r"); // sync...forces wait for planner to clear + sys_position[Y_AXIS] = 0.0; // reset the Y position + gc_sync_position(); + plan_sync_position(); + break; #endif - default: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Unknown Switch %d", index); - break; + default: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Unknown Switch %d", index); break; } } void user_m30() { char gcode_line[20]; - sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); // + sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); // inputBuffer.push(gcode_line); } diff --git a/Grbl_Esp32/Custom/custom_code_template.cpp b/Grbl_Esp32/Custom/custom_code_template.cpp index 1c68d67b..0e6f0779 100644 --- a/Grbl_Esp32/Custom/custom_code_template.cpp +++ b/Grbl_Esp32/Custom/custom_code_template.cpp @@ -51,9 +51,7 @@ enabled with USE_ defines in Machines/my_machine.h machine_init() is called when Grbl_ESP32 first starts. You can use it to do any special things your machine needs at startup. */ -void machine_init() -{ -} +void machine_init() {} #endif #ifdef USE_CUSTOM_HOMING @@ -64,10 +62,9 @@ void machine_init() example, if you need to manually prep the machine for homing, you could implement user_defined_homing() to wait for some button to be pressed, then return true. */ -bool user_defined_homing() -{ - // True = done with homing, false = continue with normal Grbl_ESP32 homing - return true; +bool user_defined_homing() { + // True = done with homing, false = continue with normal Grbl_ESP32 homing + return true; } #endif @@ -89,10 +86,9 @@ bool user_defined_homing() pl_data = planner data (see the definition of this type to see what it is) position = an N_AXIS array of where the machine is starting from for this move */ -void inverse_kinematics(float *target, plan_line_data_t *pl_data, float *position) -{ - // this simply moves to the target. Replace with your kinematics. - mc_line(target, pl_data); +void inverse_kinematics(float* target, plan_line_data_t* pl_data, float* position) { + // this simply moves to the target. Replace with your kinematics. + mc_line(target, pl_data); } /* @@ -103,15 +99,13 @@ void inverse_kinematics(float *target, plan_line_data_t *pl_data, float *positio */ bool kinematics_pre_homing(uint8_t cycle_mask)) { - return false; // finish normal homing cycle + return false; // finish normal homing cycle } /* kinematics_post_homing() is called at the end of normal homing */ -void kinematics_post_homing() -{ -} +void kinematics_post_homing() {} #endif #ifdef USE_FWD_KINEMATIC @@ -121,10 +115,9 @@ void kinematics_post_homing() Convert the N_AXIS array of motor positions to cartesian in your code. */ -void forward_kinematics(float *position) -{ - // position[X_AXIS] = - // position[Y_AXIS] = +void forward_kinematics(float* position) { + // position[X_AXIS] = + // position[Y_AXIS] = } #endif @@ -133,9 +126,7 @@ void forward_kinematics(float *position) user_tool_change() is called when tool change gcode is received, to perform appropriate actions for your machine. */ -void user_tool_change(uint8_t new_tool) -{ -} +void user_tool_change(uint8_t new_tool) {} #endif #if defined(MACRO_BUTTON_0_PIN) || defined(MACRO_BUTTON_1_PIN) || defined(MACRO_BUTTON_2_PIN) @@ -143,18 +134,14 @@ void user_tool_change(uint8_t new_tool) options. user_defined_macro() is called with the button number to perform whatever actions you choose. */ -void user_defined_macro(uint8_t index) -{ -} +void user_defined_macro(uint8_t index) {} #endif #ifdef USE_M30 /* user_m30() is called when an M30 gcode signals the end of a gcode file. */ -void user_m30() -{ -} +void user_m30() {} #endif #ifdef USE_MACHINE_TRINAMIC_INIT @@ -162,9 +149,7 @@ void user_m30() machine_triaminic_setup() replaces the normal setup of trinamic drivers with your own code. For example, you could setup StallGuard */ -void machine_trinamic_setup() -{ -} +void machine_trinamic_setup() {} #endif // If you add any additional functions specific to your machine that diff --git a/Grbl_Esp32/Custom/esp32_printer_controller.cpp b/Grbl_Esp32/Custom/esp32_printer_controller.cpp index c232a068..94420210 100644 --- a/Grbl_Esp32/Custom/esp32_printer_controller.cpp +++ b/Grbl_Esp32/Custom/esp32_printer_controller.cpp @@ -51,33 +51,32 @@ enabled with USE_ defines in Machines/my_machine.h machine_init() is called when Grbl_ESP32 first starts. You can use it to do any special things your machine needs at startup. */ -#define STEPPERS_DISABLE_PIN_X 138 -#define STEPPERS_DISABLE_PIN_Y 134 -#define STEPPERS_DISABLE_PIN_Z 131 -#define STEPPERS_DISABLE_PIN_A 139 +# define STEPPERS_DISABLE_PIN_X 138 +# define STEPPERS_DISABLE_PIN_Y 134 +# define STEPPERS_DISABLE_PIN_Z 131 +# define STEPPERS_DISABLE_PIN_A 139 -#define FAN1_PIN 13 -#define FAN2_PIN 142 -#define FAN3_PIN 143 +# define FAN1_PIN 13 +# define FAN2_PIN 142 +# define FAN3_PIN 143 -#define BED_PIN 4 -#define NOZZLE_PIN 2 +# define BED_PIN 4 +# define NOZZLE_PIN 2 -void machine_init() -{ - // Enable steppers - digitalWrite(STEPPERS_DISABLE_PIN_X, LOW); // enable - digitalWrite(STEPPERS_DISABLE_PIN_Y, LOW); // enable - digitalWrite(STEPPERS_DISABLE_PIN_Z, LOW); // enable - digitalWrite(STEPPERS_DISABLE_PIN_A, LOW); // enable +void machine_init() { + // Enable steppers + digitalWrite(STEPPERS_DISABLE_PIN_X, LOW); // enable + digitalWrite(STEPPERS_DISABLE_PIN_Y, LOW); // enable + digitalWrite(STEPPERS_DISABLE_PIN_Z, LOW); // enable + digitalWrite(STEPPERS_DISABLE_PIN_A, LOW); // enable - // digitalWrite(FAN1_PIN, LOW); // comment out for JTAG debugging + // digitalWrite(FAN1_PIN, LOW); // comment out for JTAG debugging - digitalWrite(FAN2_PIN, LOW); // disable - digitalWrite(FAN3_PIN, LOW); // disable + digitalWrite(FAN2_PIN, LOW); // disable + digitalWrite(FAN3_PIN, LOW); // disable - digitalWrite(BED_PIN, LOW); // disable - digitalWrite(NOZZLE_PIN, LOW); // disable + digitalWrite(BED_PIN, LOW); // disable + digitalWrite(NOZZLE_PIN, LOW); // disable } #endif @@ -89,10 +88,9 @@ void machine_init() example, if you need to manually prep the machine for homing, you could implement user_defined_homing() to wait for some button to be pressed, then return true. */ -bool user_defined_homing() -{ - // True = done with homing, false = continue with normal Grbl_ESP32 homing - return true; +bool user_defined_homing() { + // True = done with homing, false = continue with normal Grbl_ESP32 homing + return true; } #endif @@ -114,10 +112,9 @@ bool user_defined_homing() pl_data = planner data (see the definition of this type to see what it is) position = an N_AXIS array of where the machine is starting from for this move */ -void inverse_kinematics(float *target, plan_line_data_t *pl_data, float *position) -{ - // this simply moves to the target. Replace with your kinematics. - mc_line(target, pl_data); +void inverse_kinematics(float* target, plan_line_data_t* pl_data, float* position) { + // this simply moves to the target. Replace with your kinematics. + mc_line(target, pl_data); } /* @@ -128,15 +125,13 @@ void inverse_kinematics(float *target, plan_line_data_t *pl_data, float *positio */ bool kinematics_pre_homing(uint8_t cycle_mask)) { - return false; // finish normal homing cycle + return false; // finish normal homing cycle } /* kinematics_post_homing() is called at the end of normal homing */ -void kinematics_post_homing() -{ -} +void kinematics_post_homing() {} #endif #ifdef USE_FWD_KINEMATIC @@ -146,10 +141,9 @@ void kinematics_post_homing() Convert the N_AXIS array of motor positions to cartesian in your code. */ -void forward_kinematics(float *position) -{ - // position[X_AXIS] = - // position[Y_AXIS] = +void forward_kinematics(float* position) { + // position[X_AXIS] = + // position[Y_AXIS] = } #endif @@ -158,9 +152,7 @@ void forward_kinematics(float *position) user_tool_change() is called when tool change gcode is received, to perform appropriate actions for your machine. */ -void user_tool_change(uint8_t new_tool) -{ -} +void user_tool_change(uint8_t new_tool) {} #endif #if defined(MACRO_BUTTON_0_PIN) || defined(MACRO_BUTTON_1_PIN) || defined(MACRO_BUTTON_2_PIN) @@ -168,18 +160,14 @@ void user_tool_change(uint8_t new_tool) options. user_defined_macro() is called with the button number to perform whatever actions you choose. */ -void user_defined_macro(uint8_t index) -{ -} +void user_defined_macro(uint8_t index) {} #endif #ifdef USE_M30 /* user_m30() is called when an M30 gcode signals the end of a gcode file. */ -void user_m30() -{ -} +void user_m30() {} #endif #ifdef USE_MACHINE_TRINAMIC_INIT @@ -187,9 +175,7 @@ void user_m30() machine_triaminic_setup() replaces the normal setup of trinamic drivers with your own code. For example, you could setup StallGuard */ -void machine_trinamic_setup() -{ -} +void machine_trinamic_setup() {} #endif // If you add any additional functions specific to your machine that diff --git a/Grbl_Esp32/Custom/polar_coaster.cpp b/Grbl_Esp32/Custom/polar_coaster.cpp index 036c283c..af07238f 100644 --- a/Grbl_Esp32/Custom/polar_coaster.cpp +++ b/Grbl_Esp32/Custom/polar_coaster.cpp @@ -54,18 +54,17 @@ // in Machines/polar_coaster.h, thus causing this file to be included // from ../custom_code.cpp - -void calc_polar(float *target_xyz, float *polar, float last_angle); +void calc_polar(float* target_xyz, float* polar, float last_angle); float abs_angle(float ang); -static float last_angle = 0; +static float last_angle = 0; static float last_radius = 0; // this get called before homing // return false to complete normal home // return true to exit normal homing bool kinematics_pre_homing(uint8_t cycle_mask) { - return false; // finish normal homing cycle + return false; // finish normal homing cycle } void kinematics_post_homing() { @@ -86,17 +85,17 @@ void kinematics_post_homing() { */ -void inverse_kinematics(float *target, plan_line_data_t *pl_data, float *position) { +void inverse_kinematics(float* target, plan_line_data_t* pl_data, float* position) { //static float last_angle = 0; //static float last_radius = 0; - float dx, dy, dz; // distances in each cartesian axis - float p_dx, p_dy, p_dz; // distances in each polar axis - float dist, polar_dist; // the distances in both systems...used to determine feed rate - uint32_t segment_count; // number of segments the move will be broken in to. - float seg_target[N_AXIS]; // The target of the current segment - float polar[N_AXIS]; // target location in polar coordinates - float x_offset = gc_state.coord_system[X_AXIS] + gc_state.coord_offset[X_AXIS]; // offset from machine coordinate system - float z_offset = gc_state.coord_system[Z_AXIS] + gc_state.coord_offset[Z_AXIS]; // offset from machine coordinate system + float dx, dy, dz; // distances in each cartesian axis + float p_dx, p_dy, p_dz; // distances in each polar axis + float dist, polar_dist; // the distances in both systems...used to determine feed rate + uint32_t segment_count; // number of segments the move will be broken in to. + float seg_target[N_AXIS]; // The target of the current segment + float polar[N_AXIS]; // target location in polar coordinates + float x_offset = gc_state.coord_system[X_AXIS] + gc_state.coord_offset[X_AXIS]; // offset from machine coordinate system + float z_offset = gc_state.coord_system[Z_AXIS] + gc_state.coord_offset[Z_AXIS]; // offset from machine coordinate system //grbl_sendf(CLIENT_SERIAL, "Position: %4.2f %4.2f %4.2f \r\n", position[X_AXIS] - x_offset, position[Y_AXIS], position[Z_AXIS]); //grbl_sendf(CLIENT_SERIAL, "Target: %4.2f %4.2f %4.2f \r\n", target[X_AXIS] - x_offset, target[Y_AXIS], target[Z_AXIS]); // calculate cartesian move distance for each axis @@ -120,11 +119,11 @@ void inverse_kinematics(float *target, plan_line_data_t *pl_data, float *positio calc_polar(seg_target, polar, last_angle); // begin determining new feed rate // calculate move distance for each axis - p_dx = polar[RADIUS_AXIS] - last_radius; - p_dy = polar[POLAR_AXIS] - last_angle; - p_dz = dz; - polar_dist = sqrt((p_dx * p_dx) + (p_dy * p_dy) + (p_dz * p_dz)); // calculate the total move distance - float polar_rate_multiply = 1.0; // fail safe rate + p_dx = polar[RADIUS_AXIS] - last_radius; + p_dy = polar[POLAR_AXIS] - last_angle; + p_dz = dz; + polar_dist = sqrt((p_dx * p_dx) + (p_dy * p_dy) + (p_dz * p_dz)); // calculate the total move distance + float polar_rate_multiply = 1.0; // fail safe rate if (polar_dist == 0 || dist == 0) { // prevent 0 feed rate and division by 0 polar_rate_multiply = 1.0; // default to same feed rate @@ -141,7 +140,7 @@ void inverse_kinematics(float *target, plan_line_data_t *pl_data, float *positio polar[RADIUS_AXIS] += x_offset; polar[Z_AXIS] += z_offset; last_radius = polar[RADIUS_AXIS]; - last_angle = polar[POLAR_AXIS]; + last_angle = polar[POLAR_AXIS]; mc_line(polar, pl_data); } // TO DO don't need a feedrate for rapids @@ -160,18 +159,18 @@ position = the current machine position converted = position with forward kinematics applied. */ -void forward_kinematics(float *position) { - float original_position[N_AXIS]; // temporary storage of original - float print_position[N_AXIS]; +void forward_kinematics(float* position) { + float original_position[N_AXIS]; // temporary storage of original + float print_position[N_AXIS]; int32_t current_position[N_AXIS]; // Copy current state of the system position variable memcpy(current_position, sys_position, sizeof(sys_position)); system_convert_array_steps_to_mpos(print_position, current_position); original_position[X_AXIS] = print_position[X_AXIS] - gc_state.coord_system[X_AXIS] + gc_state.coord_offset[X_AXIS]; original_position[Y_AXIS] = print_position[Y_AXIS] - gc_state.coord_system[Y_AXIS] + gc_state.coord_offset[Y_AXIS]; original_position[Z_AXIS] = print_position[Z_AXIS] - gc_state.coord_system[Z_AXIS] + gc_state.coord_offset[Z_AXIS]; - position[X_AXIS] = cos(radians(original_position[Y_AXIS])) * original_position[X_AXIS] * -1; - position[Y_AXIS] = sin(radians(original_position[Y_AXIS])) * original_position[X_AXIS]; - position[Z_AXIS] = original_position[Z_AXIS]; // unchanged + position[X_AXIS] = cos(radians(original_position[Y_AXIS])) * original_position[X_AXIS] * -1; + position[Y_AXIS] = sin(radians(original_position[Y_AXIS])) * original_position[X_AXIS]; + position[Z_AXIS] = original_position[Z_AXIS]; // unchanged } // helper functions @@ -189,7 +188,7 @@ void forward_kinematics(float *position) { * a long job. * */ -void calc_polar(float *target_xyz, float *polar, float last_angle) { +void calc_polar(float* target_xyz, float* polar, float last_angle) { float delta_ang; // the difference from the last and next angle polar[RADIUS_AXIS] = hypot_f(target_xyz[X_AXIS], target_xyz[Y_AXIS]); if (polar[RADIUS_AXIS] == 0) { @@ -200,7 +199,7 @@ void calc_polar(float *target_xyz, float *polar, float last_angle) { polar[POLAR_AXIS] = abs_angle(polar[POLAR_AXIS]); } polar[Z_AXIS] = target_xyz[Z_AXIS]; // Z is unchanged - delta_ang = polar[POLAR_AXIS] - abs_angle(last_angle); + delta_ang = polar[POLAR_AXIS] - abs_angle(last_angle); // if the delta is above 180 degrees it means we are crossing the 0 degree line if (fabs(delta_ang) <= 180.0) polar[POLAR_AXIS] = last_angle + delta_ang; @@ -225,26 +224,24 @@ float abs_angle(float ang) { void user_defined_macro(uint8_t index) { switch (index) { #ifdef MACRO_BUTTON_0_PIN - case CONTROL_PIN_INDEX_MACRO_0: - inputBuffer.push("$H\r"); // home machine - break; + case CONTROL_PIN_INDEX_MACRO_0: + inputBuffer.push("$H\r"); // home machine + break; #endif #ifdef MACRO_BUTTON_1_PIN - case CONTROL_PIN_INDEX_MACRO_1: - inputBuffer.push("[ESP220]/1.nc\r"); // run SD card file 1.nc - break; + case CONTROL_PIN_INDEX_MACRO_1: + inputBuffer.push("[ESP220]/1.nc\r"); // run SD card file 1.nc + break; #endif #ifdef MACRO_BUTTON_2_PIN - case CONTROL_PIN_INDEX_MACRO_2: - inputBuffer.push("[ESP220]/2.nc\r"); // run SD card file 2.nc - break; + case CONTROL_PIN_INDEX_MACRO_2: + inputBuffer.push("[ESP220]/2.nc\r"); // run SD card file 2.nc + break; #endif #ifdef MACRO_BUTTON_3_PIN - case CONTROL_PIN_INDEX_MACRO_3: - break; + case CONTROL_PIN_INDEX_MACRO_3: break; #endif - default: - break; + default: break; } } diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index 26431157..f85b47e8 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -25,48 +25,41 @@ #include "Motors/MotorClass.cpp" // Declare system global variable structure -system_t sys; -int32_t sys_position[N_AXIS]; // Real-time machine (aka home) position vector in steps. -int32_t sys_probe_position[N_AXIS]; // Last probe position in machine coordinates and steps. -volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR. -volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks. -volatile uint8_t sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms. -volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides. -volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides. +system_t sys; +int32_t sys_position[N_AXIS]; // Real-time machine (aka home) position vector in steps. +int32_t sys_probe_position[N_AXIS]; // Last probe position in machine coordinates and steps. +volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR. +volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks. +volatile uint8_t sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms. +volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides. +volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides. #ifdef DEBUG - volatile uint8_t sys_rt_exec_debug; +volatile uint8_t sys_rt_exec_debug; #endif -Spindle *spindle; - - +Spindle* spindle; void setup() { #ifdef USE_I2S_OUT - i2s_out_init(); // The I2S out must be initialized before it can access the expanded GPIO port + i2s_out_init(); // The I2S out must be initialized before it can access the expanded GPIO port #endif WiFi.persistent(false); WiFi.disconnect(true); WiFi.enableSTA(false); WiFi.enableAP(false); WiFi.mode(WIFI_OFF); - serial_init(); // Setup serial baud rate and interrupts - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Grbl_ESP32 Ver %s Date %s", GRBL_VERSION, GRBL_VERSION_BUILD); // print grbl_esp32 verion info - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Compiled with ESP32 SDK:%s", ESP.getSdkVersion()); // print the SDK version + serial_init(); // Setup serial baud rate and interrupts + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Grbl_ESP32 Ver %s Date %s", GRBL_VERSION, GRBL_VERSION_BUILD); // print grbl_esp32 verion info + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Compiled with ESP32 SDK:%s", ESP.getSdkVersion()); // print the SDK version // show the map name at startup #ifdef MACHINE_NAME - #ifdef MACHINE_EXTRA - #define MACHINE_STRING MACHINE_NAME MACHINE_EXTRA - #else - #define MACHINE_STRING MACHINE_NAME - #endif report_machine_type(CLIENT_SERIAL); #endif - settings_init(); // Load Grbl settings from EEPROM - stepper_init(); // Configure stepper pins and interrupt timers + settings_init(); // Load Grbl settings from EEPROM + stepper_init(); // Configure stepper pins and interrupt timers init_motors(); - system_ini(); // Configure pinout pins and pin-change interrupt (Renamed due to conflict with esp32 files) - memset(sys_position, 0, sizeof(sys_position)); // Clear machine position. + system_ini(); // Configure pinout pins and pin-change interrupt (Renamed due to conflict with esp32 files) + memset(sys_position, 0, sizeof(sys_position)); // Clear machine position. #ifdef USE_PEN_SERVO servo_init(); #endif @@ -77,7 +70,7 @@ void setup() { solenoid_init(); #endif #ifdef USE_MACHINE_INIT - machine_init(); // user supplied function for special initialization + machine_init(); // user supplied function for special initialization #endif // Initialize system state. #ifdef FORCE_INITIALIZATION_ALARM @@ -94,7 +87,8 @@ void setup() { // not after disabling the alarm locks. Prevents motion startup blocks from crashing into // things uncontrollably. Very bad. #ifdef HOMING_INIT_LOCK - if (homing_enable->get()) sys.state = STATE_ALARM; + if (homing_enable->get()) + sys.state = STATE_ALARM; #endif spindle_select(); #ifdef ENABLE_WIFI @@ -109,26 +103,26 @@ void setup() { void loop() { // Reset system variables. uint8_t prior_state = sys.state; - memset(&sys, 0, sizeof(system_t)); // Clear system struct variable. - sys.state = prior_state; - sys.f_override = DEFAULT_FEED_OVERRIDE; // Set to 100% - sys.r_override = DEFAULT_RAPID_OVERRIDE; // Set to 100% - sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; // Set to 100% - memset(sys_probe_position, 0, sizeof(sys_probe_position)); // Clear probe position. - sys_probe_state = 0; - sys_rt_exec_state = 0; - sys_rt_exec_alarm = 0; - sys_rt_exec_motion_override = 0; + memset(&sys, 0, sizeof(system_t)); // Clear system struct variable. + sys.state = prior_state; + sys.f_override = DEFAULT_FEED_OVERRIDE; // Set to 100% + sys.r_override = DEFAULT_RAPID_OVERRIDE; // Set to 100% + sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; // Set to 100% + memset(sys_probe_position, 0, sizeof(sys_probe_position)); // Clear probe position. + sys_probe_state = 0; + sys_rt_exec_state = 0; + sys_rt_exec_alarm = 0; + sys_rt_exec_motion_override = 0; sys_rt_exec_accessory_override = 0; // Reset Grbl primary systems. - serial_reset_read_buffer(CLIENT_ALL); // Clear serial read buffer - gc_init(); // Set g-code parser to default state + serial_reset_read_buffer(CLIENT_ALL); // Clear serial read buffer + gc_init(); // Set g-code parser to default state spindle->stop(); coolant_init(); limits_init(); probe_init(); - plan_reset(); // Clear block buffer and planner variables - st_reset(); // Clear stepper subsystem variables + plan_reset(); // Clear block buffer and planner variables + st_reset(); // Clear stepper subsystem variables // Sync cleared gcode and planner positions to current system position. plan_sync_position(); gc_sync_position(); diff --git a/Grbl_Esp32/JSONencoder.cpp b/Grbl_Esp32/JSONencoder.cpp index 19fb50a0..99eb87d5 100644 --- a/Grbl_Esp32/JSONencoder.cpp +++ b/Grbl_Esp32/JSONencoder.cpp @@ -6,11 +6,7 @@ // Constructor. If _pretty is true, newlines are // inserted into the JSON string for easy reading. -JSONencoder::JSONencoder(bool pretty) : - pretty(pretty), - level(0), - str("") -{ +JSONencoder::JSONencoder(bool pretty) : pretty(pretty), level(0), str("") { count[level] = 0; } @@ -38,8 +34,7 @@ void JSONencoder::comma() { } // Private function to add a name enclosed with quotes. -void JSONencoder::quoted(const char *s) -{ +void JSONencoder::quoted(const char* s) { add('"'); str.concat(s); add('"'); @@ -65,17 +60,14 @@ void JSONencoder::dec_level() { void JSONencoder::line() { if (pretty) { add('\n'); - for (int i=0; i < 2*level; i++) { + for (int i = 0; i < 2 * level; i++) { add(' '); } } } // Constructor that supplies a default falue for "pretty" -JSONencoder::JSONencoder() : - JSONencoder(false) -{ } - +JSONencoder::JSONencoder() : JSONencoder(false) {} // Begins the JSON encoding process, creating an unnamed object void JSONencoder::begin() { @@ -90,14 +82,14 @@ String JSONencoder::end() { } // Starts a member element. -void JSONencoder::begin_member(const char *tag) { +void JSONencoder::begin_member(const char* tag) { comma_line(); quoted(tag); add(':'); } // Starts an array with "tag":[ -void JSONencoder::begin_array(const char *tag) { +void JSONencoder::begin_array(const char* tag) { begin_member(tag); add('['); inc_level(); @@ -122,32 +114,32 @@ void JSONencoder::begin_object() { // Ends an object with }. void JSONencoder::end_object() { dec_level(); - if (count[level+1] > 1) { + if (count[level + 1] > 1) { line(); } add('}'); } // Creates a "tag":"value" member from a C-style string -void JSONencoder::member(const char *tag, const char *value) { +void JSONencoder::member(const char* tag, const char* value) { begin_member(tag); quoted(value); } // Creates a "tag":"value" member from an Arduino string -void JSONencoder::member(const char *tag, String value) { +void JSONencoder::member(const char* tag, String value) { begin_member(tag); quoted(value.c_str()); } // Creates a "tag":"value" member from an integer -void JSONencoder::member(const char *tag, int value) { +void JSONencoder::member(const char* tag, int value) { member(tag, String(value)); } // Creates an Esp32_WebUI configuration item specification from // a value passed in as a C-style string. -void JSONencoder::begin_webui(const char *p, const char *help, const char *type, const char *val) { +void JSONencoder::begin_webui(const char* p, const char* help, const char* type, const char* val) { begin_object(); member("F", "network"); member("P", p); @@ -158,13 +150,13 @@ void JSONencoder::begin_webui(const char *p, const char *help, const char *type, // Creates an Esp32_WebUI configuration item specification from // an integer value. -void JSONencoder::begin_webui(const char *p, const char *help, const char *type, int val) { +void JSONencoder::begin_webui(const char* p, const char* help, const char* type, int val) { begin_webui(p, help, type, String(val).c_str()); } // Creates an Esp32_WebUI configuration item specification from // a C-style string value, with additional min and max arguments. -void JSONencoder::begin_webui(const char *p, const char *help, const char *type, const char *val, int min, int max) { +void JSONencoder::begin_webui(const char* p, const char* help, const char* type, const char* val, int min, int max) { begin_webui(p, help, type, val); member("S", max); member("M", min); diff --git a/Grbl_Esp32/JSONencoder.h b/Grbl_Esp32/JSONencoder.h index 6fd13860..863f1e83 100644 --- a/Grbl_Esp32/JSONencoder.h +++ b/Grbl_Esp32/JSONencoder.h @@ -4,19 +4,20 @@ #define MAX_JSON_LEVEL 16 class JSONencoder { - private: - bool pretty; - int level; +private: + bool pretty; + int level; String str; - int count[MAX_JSON_LEVEL]; - void add(char c) { str += c; } - void comma_line(); - void comma(); - void quoted(const char *s); - void inc_level(); - void dec_level(); - void line(); - public: + int count[MAX_JSON_LEVEL]; + void add(char c) { str += c; } + void comma_line(); + void comma(); + void quoted(const char* s); + void inc_level(); + void dec_level(); + void line(); + +public: // Constructor; set _pretty true for pretty printing JSONencoder(bool pretty); // If you don't set _pretty it defaults to false @@ -29,12 +30,12 @@ class JSONencoder { String end(); // member() creates a "tag":"value" element - void member(const char *tag, const char *value); - void member(const char *tag, String value); - void member(const char *tag, int value); + void member(const char* tag, const char* value); + void member(const char* tag, String value); + void member(const char* tag, int value); // begin_array() starts a "tag":[ array element - void begin_array(const char *tag); + void begin_array(const char* tag); // end_array() closes the array with ] void end_array(); @@ -48,7 +49,7 @@ class JSONencoder { // begin_member() starts the creation of a member. // The only case where you need to use it directly // is when you want a member whose value is an object. - void begin_member(const char *tag); + void begin_member(const char* tag); // The begin_webui() methods are specific to Esp3D_WebUI // WebUI sends JSON objects to the UI to generate configuration @@ -71,7 +72,7 @@ class JSONencoder { // S => 0 .. 255 // A => 7 .. 15 (0.0.0.0 .. 255.255.255.255) // I => 0 .. 2^31-1 - void begin_webui(const char *p, const char *help, const char *type, const char *val); - void begin_webui(const char *p, const char *help, const char *type, const int val); - void begin_webui(const char *p, const char *help, const char *type, const char *val, int min, int max); + void begin_webui(const char* p, const char* help, const char* type, const char* val); + void begin_webui(const char* p, const char* help, const char* type, const int val); + void begin_webui(const char* p, const char* help, const char* type, const char* val, int min, int max); }; diff --git a/Grbl_Esp32/Motors/MotorClass.cpp b/Grbl_Esp32/Motors/MotorClass.cpp index def78b8b..c1d7d891 100644 --- a/Grbl_Esp32/Motors/MotorClass.cpp +++ b/Grbl_Esp32/Motors/MotorClass.cpp @@ -38,21 +38,22 @@ #include "RcServoClass.cpp" //#include "SolenoidClass.cpp" -Motor* myMotor[MAX_AXES][MAX_GANGED]; // number of axes (normal and ganged) -static TaskHandle_t readSgTaskHandle = 0; // for realtime stallguard data diaplay +Motor* myMotor[MAX_AXES][MAX_GANGED]; // number of axes (normal and ganged) +static TaskHandle_t readSgTaskHandle = 0; // for realtime stallguard data diaplay static TaskHandle_t servoUpdateTaskHandle = 0; -uint8_t rmt_chan_num[MAX_AXES][MAX_GANGED]; +uint8_t rmt_chan_num[MAX_AXES][MAX_GANGED]; rmt_item32_t rmtItem[2]; rmt_config_t rmtConfig; -bool motor_class_steps; // true if at least one motor class is handling steps +bool motor_class_steps; // true if at least one motor class is handling steps void init_motors() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Init Motors"); #ifdef X_TRINAMIC_DRIVER - myMotor[X_AXIS][0] = new TrinamicDriver(X_AXIS, X_STEP_PIN, X_DIRECTION_PIN, X_DISABLE_PIN, X_CS_PIN, X_TRINAMIC_DRIVER, X_RSENSE, get_next_trinamic_driver_index()); + myMotor[X_AXIS][0] = new TrinamicDriver( + X_AXIS, X_STEP_PIN, X_DIRECTION_PIN, X_DISABLE_PIN, X_CS_PIN, X_TRINAMIC_DRIVER, X_RSENSE, get_next_trinamic_driver_index()); #elif defined(X_SERVO_PIN) myMotor[X_AXIS][0] = new RcServo(X_AXIS, X_SERVO_PIN, X_SERVO_RANGE_MIN, X_SERVO_RANGE_MAX); #elif defined(X_UNIPOLAR) @@ -64,7 +65,8 @@ void init_motors() { #endif #ifdef X2_TRINAMIC_DRIVER - myMotor[X_AXIS][1] = new TrinamicDriver(X2_AXIS, X2_STEP_PIN, X2_DIRECTION_PIN, X2_DISABLE_PIN, X2_CS_PIN, X2_TRINAMIC_DRIVER, X2_RSENSE, get_next_trinamic_driver_index()); + myMotor[X_AXIS][1] = new TrinamicDriver( + X2_AXIS, X2_STEP_PIN, X2_DIRECTION_PIN, X2_DISABLE_PIN, X2_CS_PIN, X2_TRINAMIC_DRIVER, X2_RSENSE, get_next_trinamic_driver_index()); #elif defined(X2_SERVO_PIN) myMotor[X_AXIS][1] = new RcServo(X2_AXIS, X2_SERVO_PIN, X2_SERVO_RANGE_MIN, X2_SERVO_RANGE_MAX); #elif defined(X2_UNIPOLAR) @@ -75,10 +77,10 @@ void init_motors() { myMotor[X_AXIS][1] = new Nullmotor(); #endif - // this WILL be done better with settings #ifdef Y_TRINAMIC_DRIVER - myMotor[Y_AXIS][0] = new TrinamicDriver(Y_AXIS, Y_STEP_PIN, Y_DIRECTION_PIN, Y_DISABLE_PIN, Y_CS_PIN, Y_TRINAMIC_DRIVER, Y_RSENSE, get_next_trinamic_driver_index()); + myMotor[Y_AXIS][0] = new TrinamicDriver( + Y_AXIS, Y_STEP_PIN, Y_DIRECTION_PIN, Y_DISABLE_PIN, Y_CS_PIN, Y_TRINAMIC_DRIVER, Y_RSENSE, get_next_trinamic_driver_index()); #elif defined(Y_SERVO_PIN) myMotor[Y_AXIS][0] = new RcServo(Y_AXIS, Y_SERVO_PIN, Y_SERVO_RANGE_MIN, Y_SERVO_RANGE_MAX); #elif defined(Y_UNIPOLAR) @@ -90,7 +92,8 @@ void init_motors() { #endif #ifdef Y2_TRINAMIC_DRIVER - myMotor[Y_AXIS][1] = new TrinamicDriver(Y2_AXIS, Y2_STEP_PIN, Y2_DIRECTION_PIN, Y2_DISABLE_PIN, Y2_CS_PIN, Y2_TRINAMIC_DRIVER, Y2_RSENSE, get_next_trinamic_driver_index()); + myMotor[Y_AXIS][1] = new TrinamicDriver( + Y2_AXIS, Y2_STEP_PIN, Y2_DIRECTION_PIN, Y2_DISABLE_PIN, Y2_CS_PIN, Y2_TRINAMIC_DRIVER, Y2_RSENSE, get_next_trinamic_driver_index()); #elif defined(Y2_SERVO_PIN) myMotor[Y_AXIS][1] = new RcServo(Y2_AXIS, Y2_SERVO_PIN, Y2_SERVO_RANGE_MIN, Y2_SERVO_RANGE_MAX); #elif defined(Y2_UNIPOLAR) @@ -101,10 +104,10 @@ void init_motors() { myMotor[Y_AXIS][1] = new Nullmotor(); #endif - // this WILL be done better with settings #ifdef Z_TRINAMIC_DRIVER - myMotor[Z_AXIS][0] = new TrinamicDriver(Z_AXIS, Z_STEP_PIN, Z_DIRECTION_PIN, Z_DISABLE_PIN, Z_CS_PIN, Z_TRINAMIC_DRIVER, Z_RSENSE, get_next_trinamic_driver_index()); + myMotor[Z_AXIS][0] = new TrinamicDriver( + Z_AXIS, Z_STEP_PIN, Z_DIRECTION_PIN, Z_DISABLE_PIN, Z_CS_PIN, Z_TRINAMIC_DRIVER, Z_RSENSE, get_next_trinamic_driver_index()); #elif defined(Z_SERVO_PIN) myMotor[Z_AXIS][0] = new RcServo(Z_AXIS, Z_SERVO_PIN, Z_SERVO_RANGE_MIN, Z_SERVO_RANGE_MAX); #elif defined(Z_UNIPOLAR) @@ -116,7 +119,8 @@ void init_motors() { #endif #ifdef Z2_TRINAMIC_DRIVER - myMotor[Z_AXIS][1] = new TrinamicDriver(Z2_AXIS, Z2_STEP_PIN, Z2_DIRECTION_PIN, Z2_DISABLE_PIN, Z2_CS_PIN, Z2_TRINAMIC_DRIVER, Z2_RSENSE, get_next_trinamic_driver_index()); + myMotor[Z_AXIS][1] = new TrinamicDriver( + Z2_AXIS, Z2_STEP_PIN, Z2_DIRECTION_PIN, Z2_DISABLE_PIN, Z2_CS_PIN, Z2_TRINAMIC_DRIVER, Z2_RSENSE, get_next_trinamic_driver_index()); #elif defined(Z2_SERVO_PIN) myMotor[Z_AXIS][1] = new RcServo(Z2_AXIS, Z2_SERVO_PIN, Z2_SERVO_RANGE_MIN, Z2_SERVO_RANGE_MAX); #elif defined(Z2_UNIPOLAR) @@ -129,7 +133,8 @@ void init_motors() { // this WILL be done better with settings #ifdef A_TRINAMIC_DRIVER - myMotor[A_AXIS][0] = new TrinamicDriver(A_AXIS, A_STEP_PIN, A_DIRECTION_PIN, A_DISABLE_PIN, A_CS_PIN, A_TRINAMIC_DRIVER, A_RSENSE, get_next_trinamic_driver_index()); + myMotor[A_AXIS][0] = new TrinamicDriver( + A_AXIS, A_STEP_PIN, A_DIRECTION_PIN, A_DISABLE_PIN, A_CS_PIN, A_TRINAMIC_DRIVER, A_RSENSE, get_next_trinamic_driver_index()); #elif defined(A_SERVO_PIN) myMotor[A_AXIS][0] = new RcServo(A_AXIS, A_SERVO_PIN, A_SERVO_RANGE_MIN, A_SERVO_RANGE_MAX); #elif defined(A_UNIPOLAR) @@ -141,7 +146,8 @@ void init_motors() { #endif #ifdef A2_TRINAMIC_DRIVER - myMotor[A_AXIS][1] = new TrinamicDriver(A2_AXIS, A2_STEP_PIN, A2_DIRECTION_PIN, A2_DISABLE_PIN, A2_CS_PIN, A2_TRINAMIC_DRIVER, A2_RSENSE, get_next_trinamic_driver_index()); + myMotor[A_AXIS][1] = new TrinamicDriver( + A2_AXIS, A2_STEP_PIN, A2_DIRECTION_PIN, A2_DISABLE_PIN, A2_CS_PIN, A2_TRINAMIC_DRIVER, A2_RSENSE, get_next_trinamic_driver_index()); #elif defined(A2_SERVO_PIN) myMotor[A_AXIS][1] = new RcServo(A2_AXIS, A2_SERVO_PIN, A2_SERVO_RANGE_MIN, A2_SERVO_RANGE_MAX); #elif defined(A2_UNIPOLAR) @@ -154,7 +160,8 @@ void init_motors() { // this WILL be done better with settings #ifdef B_TRINAMIC_DRIVER - myMotor[B_AXIS][0] = new TrinamicDriver(B_AXIS, B_STEP_PIN, B_DIRECTION_PIN, B_DISABLE_PIN, B_CS_PIN, B_TRINAMIC_DRIVER, B_RSENSE, get_next_trinamic_driver_index()); + myMotor[B_AXIS][0] = new TrinamicDriver( + B_AXIS, B_STEP_PIN, B_DIRECTION_PIN, B_DISABLE_PIN, B_CS_PIN, B_TRINAMIC_DRIVER, B_RSENSE, get_next_trinamic_driver_index()); #elif defined(B_SERVO_PIN) myMotor[B_AXIS][0] = new RcServo(B_AXIS, B_SERVO_PIN, B_SERVO_RANGE_MIN, B_SERVO_RANGE_MAX); #elif defined(B_UNIPOLAR) @@ -166,7 +173,8 @@ void init_motors() { #endif #ifdef B2_TRINAMIC_DRIVER - myMotor[B_AXIS][1] = new TrinamicDriver(B2_AXIS, B2_STEP_PIN, B2_DIRECTION_PIN, B2_DISABLE_PIN, B2_CS_PIN, B2_TRINAMIC_DRIVER, B2_RSENSE, get_next_trinamic_driver_index()); + myMotor[B_AXIS][1] = new TrinamicDriver( + B2_AXIS, B2_STEP_PIN, B2_DIRECTION_PIN, B2_DISABLE_PIN, B2_CS_PIN, B2_TRINAMIC_DRIVER, B2_RSENSE, get_next_trinamic_driver_index()); #elif defined(B2_SERVO_PIN) myMotor[B_AXIS][1] = new RcServo(B2_AXIS, B2_SERVO_PIN, B2_SERVO_RANGE_MIN, B2_SERVO_RANGE_MAX); #elif defined(B2_UNIPOLAR) @@ -179,7 +187,8 @@ void init_motors() { // this WILL be done better with settings #ifdef C_TRINAMIC_DRIVER - myMotor[C_AXIS][0] = new TrinamicDriver(C_AXIS, C_STEP_PIN, C_DIRECTION_PIN, C_DISABLE_PIN, C_CS_PIN, C_TRINAMIC_DRIVER, C_RSENSE, get_next_trinamic_driver_index()); + myMotor[C_AXIS][0] = new TrinamicDriver( + C_AXIS, C_STEP_PIN, C_DIRECTION_PIN, C_DISABLE_PIN, C_CS_PIN, C_TRINAMIC_DRIVER, C_RSENSE, get_next_trinamic_driver_index()); #elif defined(C_SERVO_PIN) myMotor[C_AXIS][0] = new RcServo(C_AXIS, C_SERVO_PIN, C_SERVO_RANGE_MIN, C_SERVO_RANGE_MAX); #elif defined(C_UNIPOLAR) @@ -191,7 +200,8 @@ void init_motors() { #endif #ifdef C2_TRINAMIC_DRIVER - myMotor[C_AXIS][1] = new TrinamicDriver(C2_AXIS, C2_STEP_PIN, C2_DIRECTION_PIN, C2_DISABLE_PIN, C2_CS_PIN, C2_TRINAMIC_DRIVER, C2_RSENSE, get_next_trinamic_driver_index()); + myMotor[C_AXIS][1] = new TrinamicDriver( + C2_AXIS, C2_STEP_PIN, C2_DIRECTION_PIN, C2_DISABLE_PIN, C2_CS_PIN, C2_TRINAMIC_DRIVER, C2_RSENSE, get_next_trinamic_driver_index()); #elif defined(C2_SERVO_PIN) myMotor[C_AXIS][1] = new RcServo(C2_AXIS, C2_SERVO_PIN, C2_SERVO_RANGE_MIN, C2_SERVO_RANGE_MAX); #elif defined(C2_UNIPOLAR) @@ -202,61 +212,56 @@ void init_motors() { myMotor[C_AXIS][1] = new Nullmotor(); #endif - #ifdef USE_STEPSTICK grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Using StepStick Mode"); -#ifdef STEPPER_MS1 +# ifdef STEPPER_MS1 digitalWrite(STEPPER_MS1, HIGH); pinMode(STEPPER_MS1, OUTPUT); -#endif -#ifdef STEPPER_MS2 +# endif +# ifdef STEPPER_MS2 digitalWrite(STEPPER_MS2, HIGH); pinMode(STEPPER_MS2, OUTPUT); -#endif -#ifdef STEPPER_X_MS3 +# endif +# ifdef STEPPER_X_MS3 digitalWrite(STEPPER_X_MS3, HIGH); pinMode(STEPPER_X_MS3, OUTPUT); -#endif -#ifdef STEPPER_Y_MS3 +# endif +# ifdef STEPPER_Y_MS3 digitalWrite(STEPPER_Y_MS3, HIGH); pinMode(STEPPER_Y_MS3, OUTPUT); -#endif -#ifdef STEPPER_Z_MS3 +# endif +# ifdef STEPPER_Z_MS3 digitalWrite(STEPPER_Z_MS3, HIGH); pinMode(STEPPER_Z_MS3, OUTPUT); -#endif -#ifdef STEPPER_A_MS3 +# endif +# ifdef STEPPER_A_MS3 digitalWrite(STEPPER_A_MS3, HIGH); pinMode(STEPPER_A_MS3, OUTPUT); -#endif -#ifdef STEPPER_B_MS3 +# endif +# ifdef STEPPER_B_MS3 digitalWrite(STEPPER_B_MS3, HIGH); pinMode(STEPPER_B_MS3, OUTPUT); -#endif -#ifdef STEPPER_C_MS3 +# endif +# ifdef STEPPER_C_MS3 digitalWrite(STEPPER_C_MS3, HIGH); pinMode(STEPPER_C_MS3, OUTPUT); -#endif -#ifdef STEPPER_RESET +# endif +# ifdef STEPPER_RESET // !RESET pin on steppers (MISO On Schematic) digitalWrite(STEPPER_RESET, HIGH); pinMode(STEPPER_RESET, OUTPUT); -#endif +# endif #endif if (STEPPERS_DISABLE_PIN != UNDEFINED_PIN) { - pinMode(STEPPERS_DISABLE_PIN, OUTPUT); // global motor enable pin - grbl_msg_sendf(CLIENT_SERIAL, - MSG_LEVEL_INFO, - "Global stepper disable pin:%s", - pinName(STEPPERS_DISABLE_PIN)); + pinMode(STEPPERS_DISABLE_PIN, OUTPUT); // global motor enable pin + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Global stepper disable pin:%s", pinName(STEPPERS_DISABLE_PIN)); } // certain motors need features to be turned on. Check them here for (uint8_t axis = X_AXIS; axis < N_AXIS; axis++) { for (uint8_t gang_index = 0; gang_index < 2; gang_index++) { - if (myMotor[axis][gang_index]->type_id == UNIPOLAR_MOTOR) motor_class_steps = true; @@ -272,39 +277,36 @@ void init_motors() { if (motors_have_type_id(TRINAMIC_SPI_MOTOR)) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TMCStepper Library Ver. 0x%06x", TMCSTEPPER_VERSION); - xTaskCreatePinnedToCore(readSgTask, // task - "readSgTask", // name for task - 4096, // size of task stack - NULL, // parameters - 1, // priority + xTaskCreatePinnedToCore(readSgTask, // task + "readSgTask", // name for task + 4096, // size of task stack + NULL, // parameters + 1, // priority &readSgTaskHandle, - 0 // core - ); + 0 // core + ); if (stallguard_debug_mask->get() != 0) grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Stallguard debug enabled: %d", stallguard_debug_mask->get()); } if (motors_have_type_id(RC_SERVO_MOTOR)) { - xTaskCreatePinnedToCore(servoUpdateTask, // task - "servoUpdateTask", // name for task - 4096, // size of task stack - NULL, // parameters - 1, // priority + xTaskCreatePinnedToCore(servoUpdateTask, // task + "servoUpdateTask", // name for task + 4096, // size of task stack + NULL, // parameters + 1, // priority &servoUpdateTaskHandle, - 0 // core - ); + 0 // core + ); } } - - void servoUpdateTask(void* pvParameters) { - TickType_t xLastWakeTime; + TickType_t xLastWakeTime; const TickType_t xUpdate = SERVO_TIMER_INT_FREQ; // in ticks (typically ms) - - xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time. - while (true) { // don't ever return from this or the task dies + xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time. + while (true) { // don't ever return from this or the task dies //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo update"); @@ -328,7 +330,6 @@ bool motors_have_type_id(motor_class_id_t id) { return false; } - void motors_set_disable(bool disable) { static bool previous_state = false; @@ -338,7 +339,7 @@ void motors_set_disable(bool disable) { previous_state = disable; if (step_enable_invert->get()) { - disable = !disable; // Apply pin invert. + disable = !disable; // Apply pin invert. } digitalWrite(STEPPERS_DISABLE_PIN, disable); @@ -369,7 +370,6 @@ void motors_set_homing_mode(uint8_t homing_mask, bool isHoming) { } } - void motors_set_direction_pins(uint8_t onMask) { static uint8_t previous_val = 255; // should never be this value if (previous_val == onMask) @@ -388,7 +388,7 @@ void motors_set_direction_pins(uint8_t onMask) { // need to be inserted into the order of axes. uint8_t get_next_trinamic_driver_index() { #ifdef TRINAMIC_DAISY_CHAIN - static uint8_t index = 1; // they start at 1 + static uint8_t index = 1; // they start at 1 return index++; #else return -1; @@ -397,7 +397,7 @@ uint8_t get_next_trinamic_driver_index() { // some motor objects, like unipolar need step signals void motors_step(uint8_t step_mask, uint8_t dir_mask) { - if (motor_class_steps) { // determined in init_motors if any motors need to handle steps + if (motor_class_steps) { // determined in init_motors if any motors need to handle steps for (uint8_t gang_index = 0; gang_index < 2; gang_index++) { for (uint8_t axis = X_AXIS; axis < N_AXIS; axis++) myMotor[axis][gang_index]->step(step_mask, dir_mask); @@ -409,11 +409,11 @@ void motors_step(uint8_t step_mask, uint8_t dir_mask) { This will print StallGuard data that is useful for tuning. */ void readSgTask(void* pvParameters) { - TickType_t xLastWakeTime; + TickType_t xLastWakeTime; const TickType_t xreadSg = 200; // in ticks (typically ms) - xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time. - while (true) { // don't ever return from this or the task dies + xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time. + while (true) { // don't ever return from this or the task dies if (motorSettingChanged) { motors_read_settings(); motorSettingChanged = false; @@ -428,13 +428,12 @@ void readSgTask(void* pvParameters) { myMotor[axis][gang_index]->debug_message(); } } - } // sys.state - } // if mask + } // sys.state + } // if mask vTaskDelayUntil(&xLastWakeTime, xreadSg); } } - #ifdef USE_I2S_OUT // // Override default function and insert a short delay @@ -445,31 +444,31 @@ void TMC2130Stepper::switchCSpin(bool state) { } #endif - - // ============================== Class Methods ================================================ -Motor :: Motor() { +Motor ::Motor() { type_id = MOTOR; } -void Motor :: init() { +void Motor ::init() { _homing_mask = 0; } -void Motor :: config_message() {} -void Motor :: debug_message() {} -void Motor :: read_settings() {} -void Motor :: set_disable(bool disable) {} -void Motor :: set_direction_pins(uint8_t onMask) {} -void Motor :: step(uint8_t step_mask, uint8_t dir_mask) {} -bool Motor :: test() {return true;}; // true = OK -void Motor :: update() {} +void Motor ::config_message() {} +void Motor ::debug_message() {} +void Motor ::read_settings() {} +void Motor ::set_disable(bool disable) {} +void Motor ::set_direction_pins(uint8_t onMask) {} +void Motor ::step(uint8_t step_mask, uint8_t dir_mask) {} +bool Motor ::test() { + return true; +}; // true = OK +void Motor ::update() {} -void Motor :: set_axis_name() { +void Motor ::set_axis_name() { sprintf(_axis_name, "%c%s", report_get_axis_letter(axis_index), dual_axis_index ? "2" : ""); } -void Motor :: set_homing_mode(uint8_t homing_mask, bool isHoming) { +void Motor ::set_homing_mode(uint8_t homing_mask, bool isHoming) { _homing_mask = homing_mask; } diff --git a/Grbl_Esp32/Motors/MotorClass.h b/Grbl_Esp32/Motors/MotorClass.h index 31bd0d78..a7d93b63 100644 --- a/Grbl_Esp32/Motors/MotorClass.h +++ b/Grbl_Esp32/Motors/MotorClass.h @@ -30,102 +30,92 @@ */ #include "../grbl.h" -#include // https://github.com/teemuatlut/TMCStepper +#include // https://github.com/teemuatlut/TMCStepper #include "TrinamicDriverClass.h" #include "RcServoClass.h" //#include "SolenoidClass.h" -extern uint8_t rmt_chan_num[MAX_AXES][2]; +extern uint8_t rmt_chan_num[MAX_AXES][2]; extern rmt_item32_t rmtItem[2]; extern rmt_config_t rmtConfig; -typedef enum { - MOTOR, - NULL_MOTOR, - STANDARD_MOTOR, - TRINAMIC_SPI_MOTOR, - UNIPOLAR_MOTOR, - RC_SERVO_MOTOR, - SOLENOID -} motor_class_id_t; +typedef enum { MOTOR, NULL_MOTOR, STANDARD_MOTOR, TRINAMIC_SPI_MOTOR, UNIPOLAR_MOTOR, RC_SERVO_MOTOR, SOLENOID } motor_class_id_t; // These are used for setup and to talk to the motors as a group. -void init_motors(); +void init_motors(); uint8_t get_next_trinamic_driver_index(); -bool motors_have_type_id(motor_class_id_t id); -void readSgTask(void* pvParameters); -void motors_read_settings(); -void motors_set_homing_mode(uint8_t homing_mask, bool isHoming); -void motors_set_disable(bool disable); -void motors_set_direction_pins(uint8_t onMask); -void motors_step(uint8_t step_mask, uint8_t dir_mask); -void servoUpdateTask(void* pvParameters); +bool motors_have_type_id(motor_class_id_t id); +void readSgTask(void* pvParameters); +void motors_read_settings(); +void motors_set_homing_mode(uint8_t homing_mask, bool isHoming); +void motors_set_disable(bool disable); +void motors_set_direction_pins(uint8_t onMask); +void motors_step(uint8_t step_mask, uint8_t dir_mask); +void servoUpdateTask(void* pvParameters); -extern bool motor_class_steps; // true if at least one motor class is handling steps +extern bool motor_class_steps; // true if at least one motor class is handling steps // ==================== Motor Classes ==================== class Motor { - public: +public: Motor(); - virtual void init(); // not in constructor because this also gets called when $$ settings change + virtual void init(); // not in constructor because this also gets called when $$ settings change virtual void config_message(); virtual void debug_message(); virtual void read_settings(); virtual void set_homing_mode(uint8_t homing_mask, bool isHoming); virtual void set_disable(bool disable); virtual void set_direction_pins(uint8_t onMask); - virtual void step(uint8_t step_mask, uint8_t dir_mask); // only used on Unipolar right now + virtual void step(uint8_t step_mask, uint8_t dir_mask); // only used on Unipolar right now virtual bool test(); virtual void set_axis_name(); virtual void update(); motor_class_id_t type_id; - uint8_t is_active = false; + uint8_t is_active = false; - protected: - uint8_t axis_index; // X_AXIS, etc - uint8_t dual_axis_index; // 0 = primary 1=ganged +protected: + uint8_t axis_index; // X_AXIS, etc + uint8_t dual_axis_index; // 0 = primary 1=ganged - bool _showError; - bool _use_mpos = true; + bool _showError; + bool _use_mpos = true; uint8_t _homing_mask; - char _axis_name[10];// this the name to use when reporting like "X" or "X2" + char _axis_name[10]; // this the name to use when reporting like "X" or "X2" }; -class Nullmotor : public Motor { - -}; +class Nullmotor : public Motor {}; class StandardStepper : public Motor { - public: +public: StandardStepper(); StandardStepper(uint8_t axis_index, uint8_t step_pin, uint8_t dir_pin, uint8_t disable_pin); virtual void config_message(); virtual void init(); virtual void set_direction_pins(uint8_t onMask); - void init_step_dir_pins(); + void init_step_dir_pins(); virtual void set_disable(bool disable); - uint8_t step_pin; + uint8_t step_pin; - protected: - bool _invert_step_pin; +protected: + bool _invert_step_pin; uint8_t dir_pin; uint8_t disable_pin; }; class TrinamicDriver : public StandardStepper { - public: - TrinamicDriver(uint8_t axis_index, - uint8_t step_pin, - uint8_t dir_pin, - uint8_t disable_pin, - uint8_t cs_pin, - uint16_t driver_part_number, - float r_sense, - int8_t spi_index); +public: + TrinamicDriver(uint8_t axis_index, + uint8_t step_pin, + uint8_t dir_pin, + uint8_t disable_pin, + uint8_t cs_pin, + uint16_t driver_part_number, + float r_sense, + int8_t spi_index); void config_message(); void init(); @@ -138,63 +128,63 @@ class TrinamicDriver : public StandardStepper { void set_disable(bool disable); bool test(); - private: +private: uint32_t calc_tstep(float speed, float percent); TMC2130Stepper* tmcstepper; // all other driver types are subclasses of this one - uint8_t _homing_mode; - uint8_t cs_pin = UNDEFINED_PIN; // The chip select pin (can be the same for daisy chain) - uint16_t _driver_part_number; // example: use 2130 for TMC2130 - float _r_sense; - int8_t spi_index; - protected: + uint8_t _homing_mode; + uint8_t cs_pin = UNDEFINED_PIN; // The chip select pin (can be the same for daisy chain) + uint16_t _driver_part_number; // example: use 2130 for TMC2130 + float _r_sense; + int8_t spi_index; + +protected: uint8_t _mode; uint8_t _lastMode = 255; }; - class UnipolarMotor : public Motor { - public: +public: UnipolarMotor(); UnipolarMotor(uint8_t axis_index, uint8_t pin_phase0, uint8_t pin_phase1, uint8_t pin_phase2, uint8_t pin_phase3); void init(); void config_message(); void set_disable(bool disable); - void step(uint8_t step_mask, uint8_t dir_mask); // only used on Unipolar right now + void step(uint8_t step_mask, uint8_t dir_mask); // only used on Unipolar right now - private: +private: uint8_t _pin_phase0; uint8_t _pin_phase1; uint8_t _pin_phase2; uint8_t _pin_phase3; uint8_t _current_phase; - bool _half_step; - bool _enabled; + bool _half_step; + bool _enabled; }; class RcServo : public Motor { - public: +public: RcServo(); RcServo(uint8_t axis_index, uint8_t pwm_pin, float min, float max); virtual void config_message(); virtual void init(); - void _write_pwm(uint32_t duty); + void _write_pwm(uint32_t duty); virtual void set_disable(bool disable); virtual void update(); - void read_settings(); - void set_homing_mode(bool is_homing, bool isHoming); + void read_settings(); + void set_homing_mode(bool is_homing, bool isHoming); - protected: +protected: void set_location(); void _get_calibration(); - uint8_t _pwm_pin; - uint8_t _channel_num; + uint8_t _pwm_pin; + uint8_t _channel_num; uint32_t _current_pwm_duty; - bool _disabled; + bool _disabled; float _position_min; - float _position_max; // position in millimeters + float _position_max; // position in millimeters float _homing_position; float _pwm_pulse_min; @@ -202,7 +192,7 @@ class RcServo : public Motor { }; class Solenoid : public RcServo { - public: +public: Solenoid(); Solenoid(uint8_t axis_index, gpio_num_t pwm_pin, float transition_poiont); void config_message(); @@ -210,6 +200,6 @@ class Solenoid : public RcServo { void update(); void init(); void set_disable(bool disable); - + float _transition_poiont; }; diff --git a/Grbl_Esp32/Motors/RcServoClass.cpp b/Grbl_Esp32/Motors/RcServoClass.cpp index 51253138..d6e157af 100644 --- a/Grbl_Esp32/Motors/RcServoClass.cpp +++ b/Grbl_Esp32/Motors/RcServoClass.cpp @@ -45,32 +45,30 @@ along with Grbl. If not, see . */ -RcServo :: RcServo() { +RcServo ::RcServo() {} -} - -RcServo :: RcServo(uint8_t axis_index, uint8_t pwm_pin, float min, float max) { - type_id = RC_SERVO_MOTOR; - this->axis_index = axis_index % MAX_AXES; - this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged - this->_pwm_pin = pwm_pin; - _position_min = min; - _position_max = max; +RcServo ::RcServo(uint8_t axis_index, uint8_t pwm_pin, float min, float max) { + type_id = RC_SERVO_MOTOR; + this->axis_index = axis_index % MAX_AXES; + this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged + this->_pwm_pin = pwm_pin; + _position_min = min; + _position_max = max; init(); } -void RcServo :: init() { +void RcServo ::init() { read_settings(); _channel_num = sys_get_next_PWM_chan_num(); ledcSetup(_channel_num, SERVO_PULSE_FREQ, SERVO_PULSE_RES_BITS); ledcAttachPin(_pwm_pin, _channel_num); _current_pwm_duty = 0; - is_active = true; // as opposed to NullMotors, this is a real motor + is_active = true; // as opposed to NullMotors, this is a real motor set_axis_name(); config_message(); } -void RcServo :: config_message() { +void RcServo ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Axis RC Servo motor Output:%d Min:%5.3fmm Max:%5.3fmm", @@ -106,13 +104,12 @@ void RcServo::set_homing_mode(bool is_homing, bool isHoming) { return; if (bit_istrue(homing_dir_mask->get(), bit(axis_index))) - home_pos = _position_min; + home_pos = _position_min; else home_pos = _position_max; //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo set home %d %3.2f", is_homing, home_pos); - sys_position[axis_index] = home_pos * axis_settings[axis_index]->steps_per_mm->get(); // convert to steps - + sys_position[axis_index] = home_pos * axis_settings[axis_index]->steps_per_mm->get(); // convert to steps } void RcServo::update() { @@ -121,7 +118,7 @@ void RcServo::update() { void RcServo::set_location() { uint32_t servo_pulse_len; - float servo_pos, mpos, offset; + float servo_pos, mpos, offset; // skip location if we are in alarm mode //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "locate"); @@ -132,15 +129,14 @@ void RcServo::set_location() { return; } - mpos = system_convert_axis_steps_to_mpos(sys_position, axis_index); // get the axis machine position in mm - offset = gc_state.coord_system[axis_index] + gc_state.coord_offset[axis_index]; // get the current axis work offset - servo_pos = mpos - offset; // determine the current work position + mpos = system_convert_axis_steps_to_mpos(sys_position, axis_index); // get the axis machine position in mm + offset = gc_state.coord_system[axis_index] + gc_state.coord_offset[axis_index]; // get the current axis work offset + servo_pos = mpos - offset; // determine the current work position // determine the pulse length servo_pulse_len = (uint32_t)mapConstrain(servo_pos, _position_min, _position_max, _pwm_pulse_min, _pwm_pulse_max); _write_pwm(servo_pulse_len); - } void RcServo::read_settings() { @@ -164,7 +160,11 @@ void RcServo::_get_calibration() { // make sure the max is in range // Note: Max travel is set positive via $$, but stored as a negative number if ((axis_settings[axis_index]->max_travel->get() < SERVO_CAL_MIN) || (axis_settings[axis_index]->max_travel->get() > SERVO_CAL_MAX)) { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo calibration ($13%d) value error. %3.2f Reset to 100", axis_index, axis_settings[axis_index]->max_travel->get()); + grbl_msg_sendf(CLIENT_SERIAL, + MSG_LEVEL_INFO, + "Servo calibration ($13%d) value error. %3.2f Reset to 100", + axis_index, + axis_settings[axis_index]->max_travel->get()); char reset_val[] = "100"; axis_settings[axis_index]->max_travel->setStringValue(reset_val); } @@ -172,12 +172,11 @@ void RcServo::_get_calibration() { _pwm_pulse_min = SERVO_MIN_PULSE; _pwm_pulse_max = SERVO_MAX_PULSE; - - if (bit_istrue(dir_invert_mask->get(), bit(axis_index))) { // normal direction + if (bit_istrue(dir_invert_mask->get(), bit(axis_index))) { // normal direction _cal_min = 2.0 - (axis_settings[axis_index]->steps_per_mm->get() / 100.0); _cal_max = 2.0 - (axis_settings[axis_index]->max_travel->get() / 100.0); swap(_pwm_pulse_min, _pwm_pulse_max); - } else { // inverted direction + } else { // inverted direction _cal_min = (axis_settings[axis_index]->steps_per_mm->get() / 100.0); _cal_max = (axis_settings[axis_index]->max_travel->get() / 100.0); } @@ -186,5 +185,4 @@ void RcServo::_get_calibration() { _pwm_pulse_max *= _cal_max; //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo calibration min:%1.2f max %1.2f", _pwm_pulse_min, _pwm_pulse_max); - } \ No newline at end of file diff --git a/Grbl_Esp32/Motors/RcServoClass.h b/Grbl_Esp32/Motors/RcServoClass.h index 961152b5..84dafbc5 100644 --- a/Grbl_Esp32/Motors/RcServoClass.h +++ b/Grbl_Esp32/Motors/RcServoClass.h @@ -21,25 +21,25 @@ // this is the pulse range of a the servo. Typical servos are 0.001 to 0.002 seconds // some servos have a wider range. You can adjust this here or in the calibration feature -#define SERVO_MIN_PULSE_SEC 0.001 // min pulse in seconds -#define SERVO_MAX_PULSE_SEC 0.002 // max pulse in seconds +#define SERVO_MIN_PULSE_SEC 0.001 // min pulse in seconds +#define SERVO_MAX_PULSE_SEC 0.002 // max pulse in seconds -#define SERVO_POSITION_MIN_DEFAULT 0.0 // mm -#define SERVO_POSITION_MAX_DEFAULT 20.0 // mm +#define SERVO_POSITION_MIN_DEFAULT 0.0 // mm +#define SERVO_POSITION_MAX_DEFAULT 20.0 // mm -#define SERVO_PULSE_FREQ 50 // 50Hz ...This is a standard analog servo value. Digital ones can repeat faster +#define SERVO_PULSE_FREQ 50 // 50Hz ...This is a standard analog servo value. Digital ones can repeat faster -#define SERVO_PULSE_RES_BITS 16 // bits of resolution of PWM (16 is max) -#define SERVO_PULSE_RES_COUNT 65535 // see above TODO...do the math here 2^SERVO_PULSE_RES_BITS +#define SERVO_PULSE_RES_BITS 16 // bits of resolution of PWM (16 is max) +#define SERVO_PULSE_RES_COUNT 65535 // see above TODO...do the math here 2^SERVO_PULSE_RES_BITS -#define SERVO_TIME_PER_BIT ((1.0 / (float)SERVO_PULSE_FREQ) / ((float)SERVO_PULSE_RES_COUNT) ) // seconds +#define SERVO_TIME_PER_BIT ((1.0 / (float)SERVO_PULSE_FREQ) / ((float)SERVO_PULSE_RES_COUNT)) // seconds -#define SERVO_MIN_PULSE (uint16_t)(SERVO_MIN_PULSE_SEC / SERVO_TIME_PER_BIT) // in timer counts -#define SERVO_MAX_PULSE (uint16_t)(SERVO_MAX_PULSE_SEC / SERVO_TIME_PER_BIT) // in timer counts +#define SERVO_MIN_PULSE (uint16_t)(SERVO_MIN_PULSE_SEC / SERVO_TIME_PER_BIT) // in timer counts +#define SERVO_MAX_PULSE (uint16_t)(SERVO_MAX_PULSE_SEC / SERVO_TIME_PER_BIT) // in timer counts -#define SERVO_PULSE_RANGE (SERVO_MAX_PULSE-SERVO_MIN_PULSE) +#define SERVO_PULSE_RANGE (SERVO_MAX_PULSE - SERVO_MIN_PULSE) -#define SERVO_CAL_MIN 20.0 // Percent: the minimum allowable calibration value -#define SERVO_CAL_MAX 180.0 // Percent: the maximum allowable calibration value +#define SERVO_CAL_MIN 20.0 // Percent: the minimum allowable calibration value +#define SERVO_CAL_MAX 180.0 // Percent: the maximum allowable calibration value -#define SERVO_TIMER_INT_FREQ 50.0 // Hz This is the task frequency +#define SERVO_TIMER_INT_FREQ 50.0 // Hz This is the task frequency diff --git a/Grbl_Esp32/Motors/StandardStepperClass.cpp b/Grbl_Esp32/Motors/StandardStepperClass.cpp index f4f63820..2a0490b6 100644 --- a/Grbl_Esp32/Motors/StandardStepperClass.cpp +++ b/Grbl_Esp32/Motors/StandardStepperClass.cpp @@ -21,50 +21,47 @@ along with Grbl. If not, see . */ -StandardStepper :: StandardStepper() { +StandardStepper ::StandardStepper() {} -} - -StandardStepper :: StandardStepper(uint8_t axis_index, uint8_t step_pin, uint8_t dir_pin, uint8_t disable_pin) { - type_id = STANDARD_MOTOR; - this->axis_index = axis_index % MAX_AXES; - this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged - this->step_pin = step_pin; - this->dir_pin = dir_pin; - this->disable_pin = disable_pin; +StandardStepper ::StandardStepper(uint8_t axis_index, uint8_t step_pin, uint8_t dir_pin, uint8_t disable_pin) { + type_id = STANDARD_MOTOR; + this->axis_index = axis_index % MAX_AXES; + this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged + this->step_pin = step_pin; + this->dir_pin = dir_pin; + this->disable_pin = disable_pin; init(); } -void StandardStepper :: init() { +void StandardStepper ::init() { _homing_mask = 0; - is_active = true; // as opposed to NullMotors, this is a real motor + is_active = true; // as opposed to NullMotors, this is a real motor set_axis_name(); init_step_dir_pins(); config_message(); } -void StandardStepper :: init_step_dir_pins() { +void StandardStepper ::init_step_dir_pins() { // TODO Step pin, but RMT complicates things _invert_step_pin = bit_istrue(step_invert_mask->get(), bit(axis_index)); pinMode(dir_pin, OUTPUT); #ifdef USE_RMT_STEPS - rmtConfig.rmt_mode = RMT_MODE_TX; - rmtConfig.clk_div = 20; - rmtConfig.mem_block_num = 2; - rmtConfig.tx_config.loop_en = false; - rmtConfig.tx_config.carrier_en = false; - rmtConfig.tx_config.carrier_freq_hz = 0; + rmtConfig.rmt_mode = RMT_MODE_TX; + rmtConfig.clk_div = 20; + rmtConfig.mem_block_num = 2; + rmtConfig.tx_config.loop_en = false; + rmtConfig.tx_config.carrier_en = false; + rmtConfig.tx_config.carrier_freq_hz = 0; rmtConfig.tx_config.carrier_duty_percent = 50; - rmtConfig.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW; - rmtConfig.tx_config.idle_output_en = true; + rmtConfig.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW; + rmtConfig.tx_config.idle_output_en = true; - -#ifdef STEP_PULSE_DELAY +# ifdef STEP_PULSE_DELAY rmtItem[0].duration0 = STEP_PULSE_DELAY * 4; -#else +# else rmtItem[0].duration0 = 1; -#endif +# endif rmtItem[0].duration1 = 4 * pulse_microseconds->get(); rmtItem[1].duration0 = 0; @@ -72,23 +69,22 @@ void StandardStepper :: init_step_dir_pins() { rmt_chan_num[axis_index][dual_axis_index] = sys_get_next_RMT_chan_num(); rmt_set_source_clk((rmt_channel_t)rmt_chan_num[axis_index][dual_axis_index], RMT_BASECLK_APB); - rmtConfig.channel = (rmt_channel_t)rmt_chan_num[axis_index][dual_axis_index]; + rmtConfig.channel = (rmt_channel_t)rmt_chan_num[axis_index][dual_axis_index]; rmtConfig.tx_config.idle_level = _invert_step_pin ? RMT_IDLE_LEVEL_HIGH : RMT_IDLE_LEVEL_LOW; - rmtConfig.gpio_num = gpio_num_t(step_pin); // c is a wacky lang - rmtItem[0].level0 = rmtConfig.tx_config.idle_level; - rmtItem[0].level1 = !rmtConfig.tx_config.idle_level; + rmtConfig.gpio_num = gpio_num_t(step_pin); // c is a wacky lang + rmtItem[0].level0 = rmtConfig.tx_config.idle_level; + rmtItem[0].level1 = !rmtConfig.tx_config.idle_level; rmt_config(&rmtConfig); rmt_fill_tx_items(rmtConfig.channel, &rmtItem[0], rmtConfig.mem_block_num, 0); #else pinMode(step_pin, OUTPUT); -#endif // USE_RMT_STEPS +#endif // USE_RMT_STEPS pinMode(disable_pin, OUTPUT); } - -void StandardStepper :: config_message() { +void StandardStepper ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Axis standard stepper motor Step:%s Dir:%s Disable:%s", @@ -98,10 +94,10 @@ void StandardStepper :: config_message() { pinName(disable_pin).c_str()); } -void StandardStepper :: set_direction_pins(uint8_t onMask) { +void StandardStepper ::set_direction_pins(uint8_t onMask) { digitalWrite(dir_pin, (onMask & bit(axis_index))); } -void StandardStepper :: set_disable(bool disable) { +void StandardStepper ::set_disable(bool disable) { digitalWrite(disable_pin, disable); } diff --git a/Grbl_Esp32/Motors/TrinamicDriverClass.cpp b/Grbl_Esp32/Motors/TrinamicDriverClass.cpp index 13628f90..1c76fb84 100644 --- a/Grbl_Esp32/Motors/TrinamicDriverClass.cpp +++ b/Grbl_Esp32/Motors/TrinamicDriverClass.cpp @@ -20,27 +20,27 @@ #include #include "TrinamicDriverClass.h" -TrinamicDriver :: TrinamicDriver(uint8_t axis_index, - uint8_t step_pin, - uint8_t dir_pin, - uint8_t disable_pin, - uint8_t cs_pin, - uint16_t driver_part_number, - float r_sense, - int8_t spi_index) { - type_id = TRINAMIC_SPI_MOTOR; - this->axis_index = axis_index % MAX_AXES; - this->dual_axis_index = axis_index < 6 ? 0 : 1; // 0 = primary 1 = ganged - _driver_part_number = driver_part_number; - _r_sense = r_sense; - this->step_pin = step_pin; - this->dir_pin = dir_pin; - this->disable_pin = disable_pin; - this->cs_pin = cs_pin; - this->spi_index = spi_index; +TrinamicDriver ::TrinamicDriver(uint8_t axis_index, + uint8_t step_pin, + uint8_t dir_pin, + uint8_t disable_pin, + uint8_t cs_pin, + uint16_t driver_part_number, + float r_sense, + int8_t spi_index) { + type_id = TRINAMIC_SPI_MOTOR; + this->axis_index = axis_index % MAX_AXES; + this->dual_axis_index = axis_index < 6 ? 0 : 1; // 0 = primary 1 = ganged + _driver_part_number = driver_part_number; + _r_sense = r_sense; + this->step_pin = step_pin; + this->dir_pin = dir_pin; + this->disable_pin = disable_pin; + this->cs_pin = cs_pin; + this->spi_index = spi_index; - _homing_mode = TRINAMIC_HOMING_MODE; - _homing_mask = 0; // no axes homing + _homing_mode = TRINAMIC_HOMING_MODE; + _homing_mask = 0; // no axes homing if (_driver_part_number == 2130) tmcstepper = new TMC2130Stepper(cs_pin, _r_sense, spi_index); @@ -53,7 +53,7 @@ TrinamicDriver :: TrinamicDriver(uint8_t axis_index, set_axis_name(); - init_step_dir_pins(); // from StandardStepper + init_step_dir_pins(); // from StandardStepper digitalWrite(cs_pin, HIGH); pinMode(cs_pin, OUTPUT); @@ -67,23 +67,22 @@ TrinamicDriver :: TrinamicDriver(uint8_t axis_index, // init() must be called later, after all TMC drivers have CS pins setup. } -void TrinamicDriver :: init() { - +void TrinamicDriver ::init() { SPI.begin(); // this will get called for each motor, but does not seem to hurt anything tmcstepper->begin(); - test(); // Try communicating with motor. Prints an error if there is a problem. - read_settings(); // pull info from settings + test(); // Try communicating with motor. Prints an error if there is a problem. + read_settings(); // pull info from settings set_mode(false); _homing_mask = 0; - is_active = true; // as opposed to NullMotors, this is a real motor + is_active = true; // as opposed to NullMotors, this is a real motor } /* This is the startup message showing the basic definition */ -void TrinamicDriver :: config_message() { +void TrinamicDriver ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Axis Trinamic TMC%d Step:%s Dir:%s CS:%s Disable:%s Index:%d", @@ -96,30 +95,25 @@ void TrinamicDriver :: config_message() { spi_index); } -bool TrinamicDriver :: test() { +bool TrinamicDriver ::test() { switch (tmcstepper->test_connection()) { - case 1: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test failed. Check connection", _axis_name); - return false; - case 2: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test failed. Check motor power", _axis_name); - return false; - default: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test passed", _axis_name); - return true; + case 1: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test failed. Check connection", _axis_name); return false; + case 2: + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test failed. Check motor power", _axis_name); + return false; + default: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test passed", _axis_name); return true; } } - /* Read setting and send them to the driver. Called at init() and whenever related settings change both are stored as float Amps, but TMCStepper library expects... uint16_t run (mA) float hold (as a percentage of run) */ -void TrinamicDriver :: read_settings() { +void TrinamicDriver ::read_settings() { uint16_t run_i_ma = (uint16_t)(axis_settings[axis_index]->run_current->get() * 1000.0); - float hold_i_percent; + float hold_i_percent; if (axis_settings[axis_index]->run_current->get() == 0) hold_i_percent = 0; @@ -132,10 +126,9 @@ void TrinamicDriver :: read_settings() { tmcstepper->microsteps(axis_settings[axis_index]->microsteps->get()); tmcstepper->rms_current(run_i_ma, hold_i_percent); - } -void TrinamicDriver :: set_homing_mode(uint8_t homing_mask, bool isHoming) { +void TrinamicDriver ::set_homing_mode(uint8_t homing_mask, bool isHoming) { _homing_mask = homing_mask; set_mode(isHoming); } @@ -145,8 +138,7 @@ void TrinamicDriver :: set_homing_mode(uint8_t homing_mask, bool isHoming) { Many people will want quiet and stallgaurd homing. Stallguard only run in Coolstep mode, so it will need to switch to Coolstep when homing */ -void TrinamicDriver :: set_mode(bool isHoming) { - +void TrinamicDriver ::set_mode(bool isHoming) { if (isHoming) _mode = TRINAMIC_HOMING_MODE; else @@ -157,45 +149,42 @@ void TrinamicDriver :: set_mode(bool isHoming) { _lastMode = _mode; switch (_mode) { - case TRINAMIC_MODE_STEALTHCHOP: - //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_STEALTHCHOP"); - tmcstepper->en_pwm_mode(true); - tmcstepper->pwm_autoscale(true); - tmcstepper->diag1_stall(false); - break; - case TRINAMIC_MODE_COOLSTEP: - //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_COOLSTEP"); - tmcstepper->en_pwm_mode(false); - tmcstepper->pwm_autoscale(false); - tmcstepper->TCOOLTHRS(NORMAL_TCOOLTHRS); // when to turn on coolstep - tmcstepper->THIGH(NORMAL_THIGH); - break; - case TRINAMIC_MODE_STALLGUARD: - //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_STALLGUARD"); - tmcstepper->en_pwm_mode(false); - tmcstepper->pwm_autoscale(false); - tmcstepper->TCOOLTHRS(calc_tstep(homing_feed_rate->get(), 150.0)); - tmcstepper->THIGH(calc_tstep(homing_feed_rate->get(), 60.0)); - tmcstepper->sfilt(1); - tmcstepper->diag1_stall(true); // stallguard i/o is on diag1 - tmcstepper->sgt(axis_settings[axis_index]->stallguard->get()); - break; - default: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_UNDEFINED"); + case TRINAMIC_MODE_STEALTHCHOP: + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_STEALTHCHOP"); + tmcstepper->en_pwm_mode(true); + tmcstepper->pwm_autoscale(true); + tmcstepper->diag1_stall(false); + break; + case TRINAMIC_MODE_COOLSTEP: + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_COOLSTEP"); + tmcstepper->en_pwm_mode(false); + tmcstepper->pwm_autoscale(false); + tmcstepper->TCOOLTHRS(NORMAL_TCOOLTHRS); // when to turn on coolstep + tmcstepper->THIGH(NORMAL_THIGH); + break; + case TRINAMIC_MODE_STALLGUARD: + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_STALLGUARD"); + tmcstepper->en_pwm_mode(false); + tmcstepper->pwm_autoscale(false); + tmcstepper->TCOOLTHRS(calc_tstep(homing_feed_rate->get(), 150.0)); + tmcstepper->THIGH(calc_tstep(homing_feed_rate->get(), 60.0)); + tmcstepper->sfilt(1); + tmcstepper->diag1_stall(true); // stallguard i/o is on diag1 + tmcstepper->sgt(axis_settings[axis_index]->stallguard->get()); + break; + default: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_UNDEFINED"); } - } /* This is the stallguard tuning info. It is call debug, so it could be generic across all classes. */ -void TrinamicDriver :: debug_message() { - +void TrinamicDriver ::debug_message() { uint32_t tstep = tmcstepper->TSTEP(); - if (tstep == 0xFFFFF || tstep < 1) // if axis is not moving return + if (tstep == 0xFFFFF || tstep < 1) // if axis is not moving return return; - float feedrate = st_get_realtime_rate(); //* settings.microsteps[axis_index] / 60.0 ; // convert mm/min to Hz + float feedrate = st_get_realtime_rate(); //* settings.microsteps[axis_index] / 60.0 ; // convert mm/min to Hz grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, @@ -211,17 +200,16 @@ void TrinamicDriver :: debug_message() { // tstep = TRINAMIC_FCLK / (time between 1/256 steps) // This is used to set the stallguard window from the homing speed. // The percent is the offset on the window -uint32_t TrinamicDriver :: calc_tstep(float speed, float percent) { +uint32_t TrinamicDriver ::calc_tstep(float speed, float percent) { float tstep = speed / 60.0 * axis_settings[axis_index]->steps_per_mm->get() * (float)(256 / axis_settings[axis_index]->microsteps->get()); - tstep = TRINAMIC_FCLK / tstep * percent / 100.0; + tstep = TRINAMIC_FCLK / tstep * percent / 100.0; return (uint32_t)tstep; } - // this can use the enable feature over SPI. The dedicated pin must be in the enable mode, // but that can be hardwired that way. -void TrinamicDriver :: set_disable(bool disable) { +void TrinamicDriver ::set_disable(bool disable) { //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Axis disable %d", _axis_name, disable); digitalWrite(disable_pin, disable); @@ -239,4 +227,3 @@ void TrinamicDriver :: set_disable(bool disable) { // the pin based enable could be added here. // This would be for individual motors, not the single pin for all motors. } - diff --git a/Grbl_Esp32/Motors/TrinamicDriverClass.h b/Grbl_Esp32/Motors/TrinamicDriverClass.h index e7dd0dc9..b1ab8040 100644 --- a/Grbl_Esp32/Motors/TrinamicDriverClass.h +++ b/Grbl_Esp32/Motors/TrinamicDriverClass.h @@ -19,43 +19,40 @@ along with Grbl. If not, see . */ -#define TRINAMIC_MODE_STEALTHCHOP 0 // very quiet -#define TRINAMIC_MODE_COOLSTEP 1 // everything runs cooler so higher current possible -#define TRINAMIC_MODE_STALLGUARD 2 // coolstep plus generates stall indication +#define TRINAMIC_MODE_STEALTHCHOP 0 // very quiet +#define TRINAMIC_MODE_COOLSTEP 1 // everything runs cooler so higher current possible +#define TRINAMIC_MODE_STALLGUARD 2 // coolstep plus generates stall indication -#define NORMAL_TCOOLTHRS 0xFFFFF // 20 bit is max -#define NORMAL_THIGH 0 +#define NORMAL_TCOOLTHRS 0xFFFFF // 20 bit is max +#define NORMAL_THIGH 0 -#define TMC2130_RSENSE_DEFAULT 0.11f -#define TMC5160_RSENSE_DEFAULT 0.075f +#define TMC2130_RSENSE_DEFAULT 0.11f +#define TMC5160_RSENSE_DEFAULT 0.075f #define TRINAMIC_SPI_FREQ 100000 -#define TRINAMIC_FCLK 12700000.0 // Internal clock Approx (Hz) used to calculate TSTEP from homing rate +#define TRINAMIC_FCLK 12700000.0 // Internal clock Approx (Hz) used to calculate TSTEP from homing rate // ==== defaults OK to define them in your machine definition ==== #ifndef TRINAMIC_RUN_MODE - #define TRINAMIC_RUN_MODE TRINAMIC_MODE_COOLSTEP +# define TRINAMIC_RUN_MODE TRINAMIC_MODE_COOLSTEP #endif #ifndef TRINAMIC_HOMING_MODE - #define TRINAMIC_HOMING_MODE TRINAMIC_RUN_MODE +# define TRINAMIC_HOMING_MODE TRINAMIC_RUN_MODE #endif - #ifndef TRINAMIC_TOFF_DISABLE - #define TRINAMIC_TOFF_DISABLE 0 +# define TRINAMIC_TOFF_DISABLE 0 #endif #ifndef TRINAMIC_TOFF_STEALTHCHOP - #define TRINAMIC_TOFF_STEALTHCHOP 5 +# define TRINAMIC_TOFF_STEALTHCHOP 5 #endif #ifndef TRINAMIC_TOFF_COOLSTEP - #define TRINAMIC_TOFF_COOLSTEP 3 +# define TRINAMIC_TOFF_COOLSTEP 3 #endif - - #include "MotorClass.h" -#include // https://github.com/teemuatlut/TMCStepper +#include // https://github.com/teemuatlut/TMCStepper diff --git a/Grbl_Esp32/Motors/UnipolarMotorClass.cpp b/Grbl_Esp32/Motors/UnipolarMotorClass.cpp index cd00218c..1dae539d 100644 --- a/Grbl_Esp32/Motors/UnipolarMotorClass.cpp +++ b/Grbl_Esp32/Motors/UnipolarMotorClass.cpp @@ -1,25 +1,22 @@ -UnipolarMotor :: UnipolarMotor() { +UnipolarMotor ::UnipolarMotor() {} -} +UnipolarMotor ::UnipolarMotor(uint8_t axis_index, uint8_t pin_phase0, uint8_t pin_phase1, uint8_t pin_phase2, uint8_t pin_phase3) { + type_id = UNIPOLAR_MOTOR; + this->axis_index = axis_index % MAX_AXES; + this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged + _pin_phase0 = pin_phase0; + _pin_phase1 = pin_phase1; + _pin_phase2 = pin_phase2; + _pin_phase3 = pin_phase3; - -UnipolarMotor :: UnipolarMotor(uint8_t axis_index, uint8_t pin_phase0, uint8_t pin_phase1, uint8_t pin_phase2, uint8_t pin_phase3) { - type_id = UNIPOLAR_MOTOR; - this->axis_index = axis_index % MAX_AXES; - this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged - _pin_phase0 = pin_phase0; - _pin_phase1 = pin_phase1; - _pin_phase2 = pin_phase2; - _pin_phase3 = pin_phase3; - - _half_step = true; // TODO read from settings ... microstep > 1 = half step + _half_step = true; // TODO read from settings ... microstep > 1 = half step set_axis_name(); init(); config_message(); } -void UnipolarMotor :: init() { +void UnipolarMotor ::init() { pinMode(_pin_phase0, OUTPUT); pinMode(_pin_phase1, OUTPUT); pinMode(_pin_phase2, OUTPUT); @@ -27,7 +24,7 @@ void UnipolarMotor :: init() { _current_phase = 0; } -void UnipolarMotor :: config_message() { +void UnipolarMotor ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Axis unipolar stepper motor Ph0:%s Ph1:%s Ph2:%s Ph3:%s", @@ -38,7 +35,7 @@ void UnipolarMotor :: config_message() { pinName(_pin_phase3).c_str()); } -void UnipolarMotor :: set_disable(bool disable) { +void UnipolarMotor ::set_disable(bool disable) { if (disable) { digitalWrite(_pin_phase0, 0); digitalWrite(_pin_phase1, 0); @@ -49,26 +46,26 @@ void UnipolarMotor :: set_disable(bool disable) { } void UnipolarMotor::step(uint8_t step_mask, uint8_t dir_mask) { - uint8_t _phase[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // temporary phase values...all start as off + uint8_t _phase[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; // temporary phase values...all start as off uint8_t phase_max; if (!(step_mask & bit(axis_index))) - return; // a step is not required on this interrupt + return; // a step is not required on this interrupt if (!_enabled) - return; // don't do anything, phase is not changed or lost + return; // don't do anything, phase is not changed or lost if (_half_step) phase_max = 7; else phase_max = 3; - if (dir_mask & bit(axis_index)) { // count up + if (dir_mask & bit(axis_index)) { // count up if (_current_phase == phase_max) _current_phase = 0; else _current_phase++; - } else { // count down + } else { // count down if (_current_phase == 0) _current_phase = phase_max; else @@ -90,53 +87,45 @@ void UnipolarMotor::step(uint8_t step_mask, uint8_t dir_mask) { */ if (_half_step) { switch (_current_phase) { - case 0: - _phase[0] = 1; - break; - case 1: - _phase[0] = 1; - _phase[1] = 1; - break; - case 2: - _phase[1] = 1; - break; - case 3: - _phase[1] = 1; - _phase[2] = 1; - break; - case 4: - _phase[2] = 1; - break; - case 5: - _phase[2] = 1; - _phase[3] = 1; - break; - case 6: - _phase[3] = 1; - break; - case 7: - _phase[3] = 1; - _phase[0] = 1; - break; + case 0: _phase[0] = 1; break; + case 1: + _phase[0] = 1; + _phase[1] = 1; + break; + case 2: _phase[1] = 1; break; + case 3: + _phase[1] = 1; + _phase[2] = 1; + break; + case 4: _phase[2] = 1; break; + case 5: + _phase[2] = 1; + _phase[3] = 1; + break; + case 6: _phase[3] = 1; break; + case 7: + _phase[3] = 1; + _phase[0] = 1; + break; } } else { switch (_current_phase) { - case 0: - _phase[0] = 1; - _phase[1] = 1; - break; - case 1: - _phase[1] = 1; - _phase[2] = 1; - break; - case 2: - _phase[2] = 1; - _phase[3] = 1; - break; - case 3: - _phase[3] = 1; - _phase[0] = 1; - break; + case 0: + _phase[0] = 1; + _phase[1] = 1; + break; + case 1: + _phase[1] = 1; + _phase[2] = 1; + break; + case 2: + _phase[2] = 1; + _phase[3] = 1; + break; + case 3: + _phase[3] = 1; + _phase[0] = 1; + break; } } digitalWrite(_pin_phase0, _phase[0]); diff --git a/Grbl_Esp32/Pins.h b/Grbl_Esp32/Pins.h index 2ec49060..a867bb52 100644 --- a/Grbl_Esp32/Pins.h +++ b/Grbl_Esp32/Pins.h @@ -6,7 +6,7 @@ #define I2S_OUT_PIN_BASE 128 -extern "C" int __digitalRead(uint8_t pin); +extern "C" int __digitalRead(uint8_t pin); extern "C" void __pinMode(uint8_t pin, uint8_t mode); extern "C" void __digitalWrite(uint8_t pin, uint8_t val); diff --git a/Grbl_Esp32/ProcessSettings.cpp b/Grbl_Esp32/ProcessSettings.cpp index 68cc5e14..b291acfe 100644 --- a/Grbl_Esp32/ProcessSettings.cpp +++ b/Grbl_Esp32/ProcessSettings.cpp @@ -9,17 +9,16 @@ bool auth_failed(Word* w, const char* value, auth_t auth_level) { permissions_t permissions = w->getPermissions(); switch (auth_level) { - case LEVEL_ADMIN: // Admin can do anything - return false; // Nothing is an Admin auth fail - case LEVEL_GUEST: // Guest can only access open settings + case LEVEL_ADMIN: // Admin can do anything + return false; // Nothing is an Admin auth fail + case LEVEL_GUEST: // Guest can only access open settings return permissions != WG; // Anything other than RG is Guest auth fail - case LEVEL_USER: // User is complicated... - if (!value) { // User can read anything - return false; // No read is a User auth fail + case LEVEL_USER: // User is complicated... + if (!value) { // User can read anything + return false; // No read is a User auth fail } return permissions == WA; // User cannot write WA - default: - return true; + default: return true; } } @@ -32,45 +31,45 @@ void show_setting(const char* name, const char* value, const char* description, } void settings_restore(uint8_t restore_flag) { - #ifdef WIFI_OR_BLUETOOTH - if (restore_flag & SETTINGS_RESTORE_WIFI_SETTINGS) { - #ifdef ENABLE_WIFI - wifi_config.reset_settings(); - #endif - #ifdef ENABLE_BLUETOOTH - bt_config.reset_settings(); - #endif - } - #endif +#ifdef WIFI_OR_BLUETOOTH + if (restore_flag & SETTINGS_RESTORE_WIFI_SETTINGS) { +# ifdef ENABLE_WIFI + wifi_config.reset_settings(); +# endif +# ifdef ENABLE_BLUETOOTH + bt_config.reset_settings(); +# endif + } +#endif if (restore_flag & SETTINGS_RESTORE_DEFAULTS) { bool restore_startup = restore_flag & SETTINGS_RESTORE_STARTUP_LINES; for (Setting* s = Setting::List; s; s = s->next()) { if (!s->getDescription()) { const char* name = s->getName(); - if (restore_startup) // all settings get restored - s->setDefault(); - else if ((strcmp(name, "Line0") != 0) && (strcmp(name, "Line1") != 0)) // non startup settings get restored + if (restore_startup) // all settings get restored + s->setDefault(); + else if ((strcmp(name, "Line0") != 0) && (strcmp(name, "Line1") != 0)) // non startup settings get restored s->setDefault(); } } } if (restore_flag & SETTINGS_RESTORE_PARAMETERS) { uint8_t idx; - float coord_data[N_AXIS]; + float coord_data[N_AXIS]; memset(&coord_data, 0, sizeof(coord_data)); - for (idx = 0; idx <= SETTING_INDEX_NCOORD; idx++) settings_write_coord_data(idx, coord_data); + for (idx = 0; idx <= SETTING_INDEX_NCOORD; idx++) + settings_write_coord_data(idx, coord_data); } if (restore_flag & SETTINGS_RESTORE_BUILD_INFO) { EEPROM.write(EEPROM_ADDR_BUILD_INFO, 0); - EEPROM.write(EEPROM_ADDR_BUILD_INFO + 1, 0); // Checksum + EEPROM.write(EEPROM_ADDR_BUILD_INFO + 1, 0); // Checksum EEPROM.commit(); } } // Get settings values from non volatile storage into memory -void load_settings() -{ - for (Setting *s = Setting::List; s; s = s->next()) { +void load_settings() { + for (Setting* s = Setting::List; s; s = s->next()) { s->load(); } } @@ -78,8 +77,7 @@ void load_settings() extern void make_settings(); extern void make_grbl_commands(); extern void make_web_settings(); -void settings_init() -{ +void settings_init() { EEPROM.begin(EEPROM_SIZE); make_settings(); make_web_settings(); @@ -92,17 +90,18 @@ void settings_init() // sent to gc_execute_line. It is probably also more time-critical // than actual settings, which change infrequently, so handling // it early is probably prudent. -uint8_t jog_set(uint8_t *value, auth_t auth_level, ESPResponseStream* out) { +uint8_t jog_set(uint8_t* value, auth_t auth_level, ESPResponseStream* out) { // Execute only if in IDLE or JOG states. - if (sys.state != STATE_IDLE && sys.state != STATE_JOG) return STATUS_IDLE_ERROR; + if (sys.state != STATE_IDLE && sys.state != STATE_JOG) + return STATUS_IDLE_ERROR; - // restore the $J= prefix because gc_execute_line() expects it + // restore the $J= prefix because gc_execute_line() expects it #define MAXLINE 128 char line[MAXLINE]; strcpy(line, "$J="); - strncat(line, (char *)value, MAXLINE-strlen("$J=")-1); + strncat(line, (char*)value, MAXLINE - strlen("$J=") - 1); - return gc_execute_line(line, out->client()); // NOTE: $J= is ignored inside g-code parser and used to detect jog motions. + return gc_execute_line(line, out->client()); // NOTE: $J= is ignored inside g-code parser and used to detect jog motions. } err_t show_grbl_help(const char* value, auth_t auth_level, ESPResponseStream* out) { @@ -110,13 +109,13 @@ err_t show_grbl_help(const char* value, auth_t auth_level, ESPResponseStream* ou return STATUS_OK; } -err_t report_gcode(const char *value, auth_t auth_level, ESPResponseStream* out) { +err_t report_gcode(const char* value, auth_t auth_level, ESPResponseStream* out) { report_gcode_modes(out->client()); return STATUS_OK; } void show_grbl_settings(ESPResponseStream* out, type_t type, bool wantAxis) { - for (Setting *s = Setting::List; s; s = s->next()) { + for (Setting* s = Setting::List; s; s = s->next()) { if (s->getType() == type && s->getGrblName()) { bool isAxis = s->getAxis() != NO_AXIS; // The following test could be expressed more succinctly with XOR, @@ -128,20 +127,19 @@ void show_grbl_settings(ESPResponseStream* out, type_t type, bool wantAxis) { } } err_t report_normal_settings(const char* value, auth_t auth_level, ESPResponseStream* out) { - show_grbl_settings(out, GRBL, false); // GRBL non-axis settings - show_grbl_settings(out, GRBL, true); // GRBL axis settings + show_grbl_settings(out, GRBL, false); // GRBL non-axis settings + show_grbl_settings(out, GRBL, true); // GRBL axis settings return STATUS_OK; } err_t report_extended_settings(const char* value, auth_t auth_level, ESPResponseStream* out) { - show_grbl_settings(out, GRBL, false); // GRBL non-axis settings - show_grbl_settings(out, EXTENDED, false); // Extended non-axis settings - show_grbl_settings(out, GRBL, true); // GRBL axis settings - show_grbl_settings(out, EXTENDED, true); // Extended axis settings + show_grbl_settings(out, GRBL, false); // GRBL non-axis settings + show_grbl_settings(out, EXTENDED, false); // Extended non-axis settings + show_grbl_settings(out, GRBL, true); // GRBL axis settings + show_grbl_settings(out, EXTENDED, true); // Extended axis settings return STATUS_OK; } -err_t list_grbl_names(const char* value, auth_t auth_level, ESPResponseStream* out) -{ - for (Setting *s = Setting::List; s; s = s->next()) { +err_t list_grbl_names(const char* value, auth_t auth_level, ESPResponseStream* out) { + for (Setting* s = Setting::List; s; s = s->next()) { const char* gn = s->getGrblName(); if (gn) { grbl_sendf(out->client(), "$%s => $%s\r\n", gn, s->getName()); @@ -149,20 +147,16 @@ err_t list_grbl_names(const char* value, auth_t auth_level, ESPResponseStream* o } return STATUS_OK; } -err_t list_settings(const char* value, auth_t auth_level, ESPResponseStream* out) -{ - for (Setting *s = Setting::List; s; s = s->next()) { - const char *displayValue = auth_failed(s, value, auth_level) - ? "" - : s->getStringValue(); +err_t list_settings(const char* value, auth_t auth_level, ESPResponseStream* out) { + for (Setting* s = Setting::List; s; s = s->next()) { + const char* displayValue = auth_failed(s, value, auth_level) ? "" : s->getStringValue(); show_setting(s->getName(), displayValue, NULL, out); } return STATUS_OK; } -err_t list_commands(const char* value, auth_t auth_level, ESPResponseStream* out) -{ - for (Command *cp = Command::List; cp; cp = cp->next()) { - const char* name = cp->getName(); +err_t list_commands(const char* value, auth_t auth_level, ESPResponseStream* out) { + for (Command* cp = Command::List; cp; cp = cp->next()) { + const char* name = cp->getName(); const char* oldName = cp->getGrblName(); if (oldName) { grbl_sendf(out->client(), "$%s or $%s", name, oldName); @@ -185,7 +179,8 @@ err_t toggle_check_mode(const char* value, auth_t auth_level, ESPResponseStream* mc_reset(); report_feedback_message(MESSAGE_DISABLED); } else { - if (sys.state) return (STATUS_IDLE_ERROR); // Requires no alarm mode. + if (sys.state) + return (STATUS_IDLE_ERROR); // Requires no alarm mode. sys.state = STATE_CHECK_MODE; report_feedback_message(MESSAGE_ENABLED); } @@ -199,7 +194,7 @@ err_t disable_alarm_lock(const char* value, auth_t auth_level, ESPResponseStream report_feedback_message(MESSAGE_ALARM_UNLOCK); sys.state = STATE_IDLE; // Don't run startup script. Prevents stored moves in startup from causing accidents. - } // Otherwise, no effect. + } // Otherwise, no effect. return STATUS_OK; } err_t report_ngc(const char* value, auth_t auth_level, ESPResponseStream* out) { @@ -210,12 +205,12 @@ err_t home(int cycle) { if (homing_enable->get() == false) return (STATUS_SETTING_DISABLED); if (system_check_safety_door_ajar()) - return (STATUS_CHECK_DOOR); // Block if safety door is ajar. - sys.state = STATE_HOMING; // Set system state variable + return (STATUS_CHECK_DOOR); // Block if safety door is ajar. + sys.state = STATE_HOMING; // Set system state variable mc_homing_cycle(cycle); - if (!sys.abort) { // Execute startup scripts after successful homing. - sys.state = STATE_IDLE; // Set to IDLE when complete. - st_go_idle(); // Set steppers to the settings idle state before returning. + if (!sys.abort) { // Execute startup scripts after successful homing. + sys.state = STATE_IDLE; // Set to IDLE when complete. + st_go_idle(); // Set steppers to the settings idle state before returning. if (cycle == HOMING_CYCLE_ALL) { char line[128]; system_execute_startup(line); @@ -255,12 +250,12 @@ err_t get_report_build_info(const char* value, auth_t auth_level, ESPResponseStr report_build_info(line, out->client()); return STATUS_OK; } - #ifdef ENABLE_BUILD_INFO_WRITE_COMMAND - settings_store_build_info(value); - return STATUS_OK; - #else - return STATUS_INVALID_STATEMENT; - #endif +#ifdef ENABLE_BUILD_INFO_WRITE_COMMAND + settings_store_build_info(value); + return STATUS_OK; +#else + return STATUS_INVALID_STATEMENT; +#endif } err_t report_startup_lines(const char* value, auth_t auth_level, ESPResponseStream* out) { report_startup_line(0, startup_line_0->get(), out->client()); @@ -269,20 +264,16 @@ err_t report_startup_lines(const char* value, auth_t auth_level, ESPResponseStre } std::map restoreCommands = { - #ifdef ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS - { "$", SETTINGS_RESTORE_DEFAULTS }, - { "settings", SETTINGS_RESTORE_DEFAULTS }, - #endif - #ifdef ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS - { "#", SETTINGS_RESTORE_PARAMETERS }, - { "gcode", SETTINGS_RESTORE_PARAMETERS }, - #endif - #ifdef ENABLE_RESTORE_EEPROM_WIPE_ALL - { "*", SETTINGS_RESTORE_ALL }, - { "all", SETTINGS_RESTORE_ALL }, - #endif - { "@", SETTINGS_RESTORE_WIFI_SETTINGS }, - { "wifi", SETTINGS_RESTORE_WIFI_SETTINGS }, +#ifdef ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS + { "$", SETTINGS_RESTORE_DEFAULTS }, { "settings", SETTINGS_RESTORE_DEFAULTS }, +#endif +#ifdef ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS + { "#", SETTINGS_RESTORE_PARAMETERS }, { "gcode", SETTINGS_RESTORE_PARAMETERS }, +#endif +#ifdef ENABLE_RESTORE_EEPROM_WIPE_ALL + { "*", SETTINGS_RESTORE_ALL }, { "all", SETTINGS_RESTORE_ALL }, +#endif + { "@", SETTINGS_RESTORE_WIFI_SETTINGS }, { "wifi", SETTINGS_RESTORE_WIFI_SETTINGS }, }; err_t restore_settings(const char* value, auth_t auth_level, ESPResponseStream* out) { if (!value) { @@ -315,61 +306,61 @@ err_t doJog(const char* value, auth_t auth_level, ESPResponseStream* out) { } std::map ErrorCodes = { - { STATUS_OK , "No error", }, - { STATUS_EXPECTED_COMMAND_LETTER , "Expected GCodecommand letter", }, - { STATUS_BAD_NUMBER_FORMAT , "Bad GCode number format", }, - { STATUS_INVALID_STATEMENT , "Invalid $ statement", }, - { STATUS_NEGATIVE_VALUE , "Negative value", }, - { STATUS_SETTING_DISABLED , "Setting disabled", }, - { STATUS_SETTING_STEP_PULSE_MIN , "Step pulse too short", }, - { STATUS_SETTING_READ_FAIL , "Failed to read settings", }, - { STATUS_IDLE_ERROR , "Command requires idle state", }, - { STATUS_SYSTEM_GC_LOCK , "GCode cannot be executed in lock or alarm state", }, - { STATUS_SOFT_LIMIT_ERROR , "Soft limit error", }, - { STATUS_OVERFLOW , "Line too long", }, - { STATUS_MAX_STEP_RATE_EXCEEDED , "Max step rate exceeded", }, - { STATUS_CHECK_DOOR , "Check door", }, - { STATUS_LINE_LENGTH_EXCEEDED , "Startup line too long", }, - { STATUS_TRAVEL_EXCEEDED , "Max travel exceeded during jog", }, - { STATUS_INVALID_JOG_COMMAND , "Invalid jog command", }, - { STATUS_SETTING_DISABLED_LASER , "Laser mode requires PWM output", }, - { STATUS_GCODE_UNSUPPORTED_COMMAND , "Unsupported GCode command", }, - { STATUS_GCODE_MODAL_GROUP_VIOLATION , "Gcode modal group violation", }, - { STATUS_GCODE_UNDEFINED_FEED_RATE , "Gcode undefined feed rate", }, - { STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER , "Gcode command value not integer", }, - { STATUS_GCODE_AXIS_COMMAND_CONFLICT , "Gcode axis command conflict", }, - { STATUS_GCODE_WORD_REPEATED , "Gcode word repeated", }, - { STATUS_GCODE_NO_AXIS_WORDS , "Gcode no axis words", }, - { STATUS_GCODE_INVALID_LINE_NUMBER , "Gcode invalid line number", }, - { STATUS_GCODE_VALUE_WORD_MISSING , "Gcode value word missing", }, - { STATUS_GCODE_UNSUPPORTED_COORD_SYS , "Gcode unsupported coordinate system", }, - { STATUS_GCODE_G53_INVALID_MOTION_MODE , "Gcode G53 invalid motion mode", }, - { STATUS_GCODE_AXIS_WORDS_EXIST , "Gcode extra axis words", }, - { STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE , "Gcode no axis words in plane", }, - { STATUS_GCODE_INVALID_TARGET , "Gcode invalid target", }, - { STATUS_GCODE_ARC_RADIUS_ERROR , "Gcode arc radius error", }, - { STATUS_GCODE_NO_OFFSETS_IN_PLANE , "Gcode no offsets in plane", }, - { STATUS_GCODE_UNUSED_WORDS , "Gcode unused words", }, - { STATUS_GCODE_G43_DYNAMIC_AXIS_ERROR , "Gcode G43 dynamic axis error", }, - { STATUS_GCODE_MAX_VALUE_EXCEEDED , "Gcode max value exceeded", }, - { STATUS_P_PARAM_MAX_EXCEEDED , "P param max exceeded", }, - { STATUS_SD_FAILED_MOUNT , "SD failed mount", }, - { STATUS_SD_FAILED_READ , "SD failed read", }, - { STATUS_SD_FAILED_OPEN_DIR , "SD failed to open directory", }, - { STATUS_SD_DIR_NOT_FOUND , "SD directory not found", }, - { STATUS_SD_FILE_EMPTY , "SD file empty", }, - { STATUS_SD_FILE_NOT_FOUND , "SD file not found", }, - { STATUS_SD_FAILED_OPEN_FILE , "SD failed to open file", }, - { STATUS_SD_FAILED_BUSY , "SD is busy", }, - { STATUS_SD_FAILED_DEL_DIR, "SD failed to delete directory", }, - { STATUS_SD_FAILED_DEL_FILE, "SD failed to delete file", }, - { STATUS_BT_FAIL_BEGIN , "Bluetooth failed to start", }, - { STATUS_WIFI_FAIL_BEGIN , "WiFi failed to start", }, - { STATUS_NUMBER_RANGE , "Number out of range for setting", }, - { STATUS_INVALID_VALUE , "Invalid value for setting", }, - { STATUS_MESSAGE_FAILED , "Failed to send message", }, - { STATUS_NVS_SET_FAILED , "Failed to store setting", }, - { STATUS_AUTHENTICATION_FAILED, "Authentication failed!", }, + { STATUS_OK, "No error" }, + { STATUS_EXPECTED_COMMAND_LETTER, "Expected GCodecommand letter" }, + { STATUS_BAD_NUMBER_FORMAT, "Bad GCode number format" }, + { STATUS_INVALID_STATEMENT, "Invalid $ statement" }, + { STATUS_NEGATIVE_VALUE, "Negative value" }, + { STATUS_SETTING_DISABLED, "Setting disabled" }, + { STATUS_SETTING_STEP_PULSE_MIN, "Step pulse too short" }, + { STATUS_SETTING_READ_FAIL, "Failed to read settings" }, + { STATUS_IDLE_ERROR, "Command requires idle state" }, + { STATUS_SYSTEM_GC_LOCK, "GCode cannot be executed in lock or alarm state" }, + { STATUS_SOFT_LIMIT_ERROR, "Soft limit error" }, + { STATUS_OVERFLOW, "Line too long" }, + { STATUS_MAX_STEP_RATE_EXCEEDED, "Max step rate exceeded" }, + { STATUS_CHECK_DOOR, "Check door" }, + { STATUS_LINE_LENGTH_EXCEEDED, "Startup line too long" }, + { STATUS_TRAVEL_EXCEEDED, "Max travel exceeded during jog" }, + { STATUS_INVALID_JOG_COMMAND, "Invalid jog command" }, + { STATUS_SETTING_DISABLED_LASER, "Laser mode requires PWM output" }, + { STATUS_GCODE_UNSUPPORTED_COMMAND, "Unsupported GCode command" }, + { STATUS_GCODE_MODAL_GROUP_VIOLATION, "Gcode modal group violation" }, + { STATUS_GCODE_UNDEFINED_FEED_RATE, "Gcode undefined feed rate" }, + { STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER, "Gcode command value not integer" }, + { STATUS_GCODE_AXIS_COMMAND_CONFLICT, "Gcode axis command conflict" }, + { STATUS_GCODE_WORD_REPEATED, "Gcode word repeated" }, + { STATUS_GCODE_NO_AXIS_WORDS, "Gcode no axis words" }, + { STATUS_GCODE_INVALID_LINE_NUMBER, "Gcode invalid line number" }, + { STATUS_GCODE_VALUE_WORD_MISSING, "Gcode value word missing" }, + { STATUS_GCODE_UNSUPPORTED_COORD_SYS, "Gcode unsupported coordinate system" }, + { STATUS_GCODE_G53_INVALID_MOTION_MODE, "Gcode G53 invalid motion mode" }, + { STATUS_GCODE_AXIS_WORDS_EXIST, "Gcode extra axis words" }, + { STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE, "Gcode no axis words in plane" }, + { STATUS_GCODE_INVALID_TARGET, "Gcode invalid target" }, + { STATUS_GCODE_ARC_RADIUS_ERROR, "Gcode arc radius error" }, + { STATUS_GCODE_NO_OFFSETS_IN_PLANE, "Gcode no offsets in plane" }, + { STATUS_GCODE_UNUSED_WORDS, "Gcode unused words" }, + { STATUS_GCODE_G43_DYNAMIC_AXIS_ERROR, "Gcode G43 dynamic axis error" }, + { STATUS_GCODE_MAX_VALUE_EXCEEDED, "Gcode max value exceeded" }, + { STATUS_P_PARAM_MAX_EXCEEDED, "P param max exceeded" }, + { STATUS_SD_FAILED_MOUNT, "SD failed mount" }, + { STATUS_SD_FAILED_READ, "SD failed read" }, + { STATUS_SD_FAILED_OPEN_DIR, "SD failed to open directory" }, + { STATUS_SD_DIR_NOT_FOUND, "SD directory not found" }, + { STATUS_SD_FILE_EMPTY, "SD file empty" }, + { STATUS_SD_FILE_NOT_FOUND, "SD file not found" }, + { STATUS_SD_FAILED_OPEN_FILE, "SD failed to open file" }, + { STATUS_SD_FAILED_BUSY, "SD is busy" }, + { STATUS_SD_FAILED_DEL_DIR, "SD failed to delete directory" }, + { STATUS_SD_FAILED_DEL_FILE, "SD failed to delete file" }, + { STATUS_BT_FAIL_BEGIN, "Bluetooth failed to start" }, + { STATUS_WIFI_FAIL_BEGIN, "WiFi failed to start" }, + { STATUS_NUMBER_RANGE, "Number out of range for setting" }, + { STATUS_INVALID_VALUE, "Invalid value for setting" }, + { STATUS_MESSAGE_FAILED, "Failed to send message" }, + { STATUS_NVS_SET_FAILED, "Failed to store setting" }, + { STATUS_AUTHENTICATION_FAILED, "Authentication failed!" }, }; const char* errorString(err_t errorNumber) { @@ -379,7 +370,7 @@ const char* errorString(err_t errorNumber) { err_t listErrorCodes(const char* value, auth_t auth_level, ESPResponseStream* out) { if (value) { - char* endptr = NULL; + char* endptr = NULL; uint8_t errorNumber = strtol(value, &endptr, 10); if (*endptr) { grbl_sendf(out->client(), "Malformed error number: %s\r\n", value); @@ -395,55 +386,52 @@ err_t listErrorCodes(const char* value, auth_t auth_level, ESPResponseStream* ou } } - for (auto it = ErrorCodes.begin(); - it != ErrorCodes.end(); - it++) { + for (auto it = ErrorCodes.begin(); it != ErrorCodes.end(); it++) { grbl_sendf(out->client(), "%d: %s\r\n", it->first, it->second); } return STATUS_OK; } - // Commands use the same syntax as Settings, but instead of setting or // displaying a persistent value, a command causes some action to occur. // That action could be anything, from displaying a run-time parameter // to performing some system state change. Each command is responsible // for decoding its own value string, if it needs one. void make_grbl_commands() { - new GrblCommand("", "Help", show_grbl_help, ANY_STATE); - new GrblCommand("T", "State", showState, ANY_STATE); - new GrblCommand("J", "Jog", doJog, IDLE_OR_JOG); + new GrblCommand("", "Help", show_grbl_help, ANY_STATE); + new GrblCommand("T", "State", showState, ANY_STATE); + new GrblCommand("J", "Jog", doJog, IDLE_OR_JOG); - new GrblCommand("$", "GrblSettings/List", report_normal_settings, NOT_CYCLE_OR_HOLD); - new GrblCommand("+", "ExtendedSettings/List", report_extended_settings, NOT_CYCLE_OR_HOLD); - new GrblCommand("L", "GrblNames/List", list_grbl_names, NOT_CYCLE_OR_HOLD); - new GrblCommand("S", "Settings/List", list_settings, NOT_CYCLE_OR_HOLD); - new GrblCommand("CMD", "Commands/List", list_commands, NOT_CYCLE_OR_HOLD); - new GrblCommand("E", "ErrorCodes/List",listErrorCodes, ANY_STATE); - new GrblCommand("G", "GCode/Modes", report_gcode, ANY_STATE); - new GrblCommand("C", "GCode/Check", toggle_check_mode, ANY_STATE); - new GrblCommand("X", "Alarm/Disable", disable_alarm_lock, ANY_STATE); + new GrblCommand("$", "GrblSettings/List", report_normal_settings, NOT_CYCLE_OR_HOLD); + new GrblCommand("+", "ExtendedSettings/List", report_extended_settings, NOT_CYCLE_OR_HOLD); + new GrblCommand("L", "GrblNames/List", list_grbl_names, NOT_CYCLE_OR_HOLD); + new GrblCommand("S", "Settings/List", list_settings, NOT_CYCLE_OR_HOLD); + new GrblCommand("CMD", "Commands/List", list_commands, NOT_CYCLE_OR_HOLD); + new GrblCommand("E", "ErrorCodes/List", listErrorCodes, ANY_STATE); + new GrblCommand("G", "GCode/Modes", report_gcode, ANY_STATE); + new GrblCommand("C", "GCode/Check", toggle_check_mode, ANY_STATE); + new GrblCommand("X", "Alarm/Disable", disable_alarm_lock, ANY_STATE); new GrblCommand("NVX", "Settings/Erase", Setting::eraseNVS, IDLE_OR_ALARM, WA); - new GrblCommand("V", "Settings/Stats", Setting::report_nvs_stats, IDLE_OR_ALARM); - new GrblCommand("#", "GCode/Offsets", report_ngc, IDLE_OR_ALARM); - new GrblCommand("H", "Home", home_all, IDLE_OR_ALARM); - #ifdef HOMING_SINGLE_AXIS_COMMANDS - new GrblCommand("HX", "Home/X", home_x, IDLE_OR_ALARM); - new GrblCommand("HY", "Home/Y", home_y, IDLE_OR_ALARM); - new GrblCommand("HZ", "Home/Z", home_z, IDLE_OR_ALARM); - #if (N_AXIS > 3) - new GrblCommand("HA", "Home/A", home_a, IDLE_OR_ALARM); - #endif - #if (N_AXIS > 4) - new GrblCommand("HB", "Home/B", home_b, IDLE_OR_ALARM); - #endif - #if (N_AXIS > 5) - new GrblCommand("HC", "Home/C", home_c, IDLE_OR_ALARM); - #endif - #endif + new GrblCommand("V", "Settings/Stats", Setting::report_nvs_stats, IDLE_OR_ALARM); + new GrblCommand("#", "GCode/Offsets", report_ngc, IDLE_OR_ALARM); + new GrblCommand("H", "Home", home_all, IDLE_OR_ALARM); +#ifdef HOMING_SINGLE_AXIS_COMMANDS + new GrblCommand("HX", "Home/X", home_x, IDLE_OR_ALARM); + new GrblCommand("HY", "Home/Y", home_y, IDLE_OR_ALARM); + new GrblCommand("HZ", "Home/Z", home_z, IDLE_OR_ALARM); +# if (N_AXIS > 3) + new GrblCommand("HA", "Home/A", home_a, IDLE_OR_ALARM); +# endif +# if (N_AXIS > 4) + new GrblCommand("HB", "Home/B", home_b, IDLE_OR_ALARM); +# endif +# if (N_AXIS > 5) + new GrblCommand("HC", "Home/C", home_c, IDLE_OR_ALARM); +# endif +#endif new GrblCommand("SLP", "System/Sleep", sleep_grbl, IDLE_OR_ALARM); - new GrblCommand("I", "Build/Info", get_report_build_info, IDLE_OR_ALARM); - new GrblCommand("N", "GCode/StartupLines", report_startup_lines, IDLE_OR_ALARM); + new GrblCommand("I", "Build/Info", get_report_build_info, IDLE_OR_ALARM); + new GrblCommand("N", "GCode/StartupLines", report_startup_lines, IDLE_OR_ALARM); new GrblCommand("RST", "Settings/Restore", restore_settings, IDLE_OR_ALARM, WA); }; @@ -452,7 +440,7 @@ void make_grbl_commands() { // start points to a null-terminated string. // Returns the first substring that does not contain whitespace. // Case is unchanged because comparisons are case-insensitive. -char *normalize_key(char *start) { +char* normalize_key(char* start) { char c; // In the usual case, this loop will exit on the very first test, @@ -469,9 +457,8 @@ char *normalize_key(char *start) { // Having found the beginning of the printable string, // we now scan forward until we find a space character. - char *end; - for (end = start; (c = *end) != '\0' && !isspace(c); end++) { - } + char* end; + for (end = start; (c = *end) != '\0' && !isspace(c); end++) {} // end now points to either a whitespace character of end of string // In either case it is okay to place a null there @@ -482,7 +469,7 @@ char *normalize_key(char *start) { // This is the handler for all forms of settings commands, // $..= and [..], with and without a value. -err_t do_command_or_setting(const char *key, char *value, auth_t auth_level, ESPResponseStream* out) { +err_t do_command_or_setting(const char* key, char* value, auth_t auth_level, ESPResponseStream* out) { // If value is NULL, it means that there was no value string, i.e. // $key without =, or [key] with nothing following. // If value is not NULL, but the string is empty, that is the form @@ -491,7 +478,7 @@ err_t do_command_or_setting(const char *key, char *value, auth_t auth_level, ESP // First search the settings list by text name. If found, set a new // value if one is given, otherwise display the current value - for (Setting *s = Setting::List; s; s = s->next()) { + for (Setting* s = Setting::List; s; s = s->next()) { if (strcasecmp(s->getName(), key) == 0) { if (auth_failed(s, value, auth_level)) { return STATUS_AUTHENTICATION_FAILED; @@ -507,7 +494,7 @@ err_t do_command_or_setting(const char *key, char *value, auth_t auth_level, ESP // Then search the setting list by compatible name. If found, set a new // value if one is given, otherwise display the current value in compatible mode - for (Setting *s = Setting::List; s; s = s->next()) { + for (Setting* s = Setting::List; s; s = s->next()) { if (s->getGrblName() && strcasecmp(s->getGrblName(), key) == 0) { if (auth_failed(s, value, auth_level)) { return STATUS_AUTHENTICATION_FAILED; @@ -523,12 +510,8 @@ err_t do_command_or_setting(const char *key, char *value, auth_t auth_level, ESP // If we did not find a setting, look for a command. Commands // handle values internally; you cannot determine whether to set // or display solely based on the presence of a value. - for (Command *cp = Command::List; cp; cp = cp->next()) { - if ( (strcasecmp(cp->getName(), key) == 0) - || (cp->getGrblName() - && strcasecmp(cp->getGrblName(), key) == 0 - ) - ) { + for (Command* cp = Command::List; cp; cp = cp->next()) { + if ((strcasecmp(cp->getName(), key) == 0) || (cp->getGrblName() && strcasecmp(cp->getGrblName(), key) == 0)) { if (auth_failed(cp, value, auth_level)) { return STATUS_AUTHENTICATION_FAILED; } @@ -547,18 +530,16 @@ err_t do_command_or_setting(const char *key, char *value, auth_t auth_level, ESP // This lets us look at X axis settings with $*x. // $x by itself is the disable alarm lock command if (lcKey.startsWith("*")) { - lcKey.remove(0,1); + lcKey.remove(0, 1); } lcKey.toLowerCase(); bool found = false; - for (Setting *s = Setting::List; s; s = s->next()) { + for (Setting* s = Setting::List; s; s = s->next()) { auto lcTest = String(s->getName()); lcTest.toLowerCase(); if (lcTest.indexOf(lcKey) >= 0) { - const char *displayValue = auth_failed(s, value, auth_level) - ? "" - : s->getStringValue(); + const char* displayValue = auth_failed(s, value, auth_level) ? "" : s->getStringValue(); show_setting(s->getName(), displayValue, NULL, out); found = true; } @@ -573,8 +554,8 @@ err_t do_command_or_setting(const char *key, char *value, auth_t auth_level, ESP uint8_t system_execute_line(char* line, ESPResponseStream* out, auth_t auth_level) { remove_password(line, auth_level); - char *value; - if (*line++ == '[') { // [ESPxxx] form + char* value; + if (*line++ == '[') { // [ESPxxx] form value = strrchr(line, ']'); if (!value) { // Missing ] is an error in this form @@ -595,7 +576,7 @@ uint8_t system_execute_line(char* line, ESPResponseStream* out, auth_t auth_leve } } - char *key = normalize_key(line); + char* key = normalize_key(line); // At this point there are three possibilities for value // NULL - $xxx without = @@ -610,7 +591,7 @@ uint8_t system_execute_line(char* line, uint8_t client, auth_t auth_level) { void system_execute_startup(char* line) { err_t status_code; - char gcline[256]; + char gcline[256]; strncpy(gcline, startup_line_0->get(), 255); if (*gcline) { status_code = gc_execute_line(gcline, CLIENT_SERIAL); @@ -622,4 +603,3 @@ void system_execute_startup(char* line) { report_execute_startup_message(gcline, status_code, CLIENT_SERIAL); } } - diff --git a/Grbl_Esp32/SettingsClass.cpp b/Grbl_Esp32/SettingsClass.cpp index 4825aae3..6641d4de 100644 --- a/Grbl_Esp32/SettingsClass.cpp +++ b/Grbl_Esp32/SettingsClass.cpp @@ -3,29 +3,23 @@ #include #include "nvs.h" -Word::Word(type_t type, permissions_t permissions, const char* description, const char* grblName, const char* fullName) - : _description(description) - , _grblName(grblName) - , _fullName(fullName) - , _type(type) - , _permissions(permissions) -{} +Word::Word(type_t type, permissions_t permissions, const char* description, const char* grblName, const char* fullName) : + _description(description), _grblName(grblName), _fullName(fullName), _type(type), _permissions(permissions) {} Command* Command::List = NULL; -Command::Command(const char* description, type_t type, permissions_t permissions, const char* grblName, const char* fullName) - : Word(type, permissions, description, grblName, fullName) -{ +Command::Command(const char* description, type_t type, permissions_t permissions, const char* grblName, const char* fullName) : + Word(type, permissions, description, grblName, fullName) { link = List; List = this; } Setting* Setting::List = NULL; -Setting::Setting(const char* description, type_t type, permissions_t permissions, const char* grblName, const char* fullName, bool (*checker)(char *)) - : Word(type, permissions, description, grblName, fullName) - , _checker(checker) -{ +Setting::Setting( + const char* description, type_t type, permissions_t permissions, const char* grblName, const char* fullName, bool (*checker)(char*)) : + Word(type, permissions, description, grblName, fullName), + _checker(checker) { link = List; List = this; @@ -36,9 +30,9 @@ Setting::Setting(const char* description, type_t type, permissions_t permissions _keyName = _fullName; } else { // This is Donald Knuth's hash function from Vol 3, chapter 6.4 - char *hashName = (char *)malloc(16); - uint32_t hash = len; - for (const char *s = fullName; *s; s++) { + char* hashName = (char*)malloc(16); + uint32_t hash = len; + for (const char* s = fullName; *s; s++) { hash = ((hash << 5) ^ (hash >> 27)) ^ (*s); } sprintf(hashName, "%.7s%08x", fullName, hash); @@ -46,7 +40,7 @@ Setting::Setting(const char* description, type_t type, permissions_t permissions } } -err_t Setting::check(char *s) { +err_t Setting::check(char* s) { if (sys.state != STATE_IDLE && !(sys.state & STATE_ALARM)) { return STATUS_IDLE_ERROR; } @@ -66,18 +60,22 @@ void Setting::init() { } } -IntSetting::IntSetting(const char *description, type_t type, permissions_t permissions, const char* grblName, const char* name, int32_t defVal, int32_t minVal, int32_t maxVal, bool (*checker)(char *) = NULL) - : Setting(description, type, permissions, grblName, name, checker) - , _defaultValue(defVal) - , _currentValue(defVal) - , _minValue(minVal) - , _maxValue(maxVal) -{ } +IntSetting::IntSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + int32_t defVal, + int32_t minVal, + int32_t maxVal, + bool (*checker)(char*) = NULL) : + Setting(description, type, permissions, grblName, name, checker), + _defaultValue(defVal), _currentValue(defVal), _minValue(minVal), _maxValue(maxVal) {} void IntSetting::load() { esp_err_t err = nvs_get_i32(_handle, _keyName, &_storedValue); if (err) { - _storedValue = std::numeric_limits::min(); + _storedValue = std::numeric_limits::min(); _currentValue = _defaultValue; } else { _currentValue = _storedValue; @@ -96,7 +94,7 @@ err_t IntSetting::setStringValue(char* s) { if (err_t err = check(s)) { return err; } - char* endptr; + char* endptr; int32_t convertedValue = strtol(s, &endptr, 10); if (endptr == s || *endptr != '\0') { return STATUS_BAD_NUMBER_FORMAT; @@ -124,23 +122,27 @@ const char* IntSetting::getStringValue() { return strval; } -void IntSetting::addWebui(JSONencoder *j) { +void IntSetting::addWebui(JSONencoder* j) { if (getDescription()) { j->begin_webui(getName(), getDescription(), "I", getStringValue(), _minValue, _maxValue); j->end_object(); } } -AxisMaskSetting::AxisMaskSetting(const char *description, type_t type, permissions_t permissions, const char* grblName, const char* name, int32_t defVal, bool (*checker)(char *) = NULL) - : Setting(description, type, permissions, grblName, name, checker) - , _defaultValue(defVal) - , _currentValue(defVal) -{ } +AxisMaskSetting::AxisMaskSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + int32_t defVal, + bool (*checker)(char*) = NULL) : + Setting(description, type, permissions, grblName, name, checker), + _defaultValue(defVal), _currentValue(defVal) {} void AxisMaskSetting::load() { esp_err_t err = nvs_get_i32(_handle, _keyName, &_storedValue); if (err) { - _storedValue = -1; + _storedValue = -1; _currentValue = _defaultValue; } else { _currentValue = _storedValue; @@ -160,7 +162,7 @@ err_t AxisMaskSetting::setStringValue(char* s) { return err; } int32_t convertedValue; - char* endptr; + char* endptr; if (*s == '\0') { convertedValue = 0; } else { @@ -200,8 +202,8 @@ const char* AxisMaskSetting::getCompatibleValue() { const char* AxisMaskSetting::getStringValue() { static char strval[32]; - char *s = strval; - uint32_t mask = get(); + char* s = strval; + uint32_t mask = get(); for (int i = 0; i < MAX_N_AXIS; i++) { if (mask & bit(i)) { *s++ = "XYZABC"[i]; @@ -211,20 +213,24 @@ const char* AxisMaskSetting::getStringValue() { return strval; } -void AxisMaskSetting::addWebui(JSONencoder *j) { +void AxisMaskSetting::addWebui(JSONencoder* j) { if (getDescription()) { - j->begin_webui(getName(), getDescription(), "I", getStringValue(), 0, (1<begin_webui(getName(), getDescription(), "I", getStringValue(), 0, (1 << MAX_N_AXIS) - 1); j->end_object(); } } -FloatSetting::FloatSetting(const char *description, type_t type, permissions_t permissions, const char* grblName, const char* name, float defVal, float minVal, float maxVal, bool (*checker)(char *) = NULL) - : Setting(description, type, permissions, grblName, name, checker) - , _defaultValue(defVal) - , _currentValue(defVal) - , _minValue(minVal) - , _maxValue(maxVal) -{ } +FloatSetting::FloatSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + float defVal, + float minVal, + float maxVal, + bool (*checker)(char*) = NULL) : + Setting(description, type, permissions, grblName, name, checker), + _defaultValue(defVal), _currentValue(defVal), _minValue(minVal), _maxValue(maxVal) {} void FloatSetting::load() { union { @@ -251,12 +257,10 @@ err_t FloatSetting::setStringValue(char* s) { return err; } - float convertedValue; - uint8_t len = strlen(s); + float convertedValue; + uint8_t len = strlen(s); uint8_t retlen = 0; - if (!read_float(s, &retlen, &convertedValue) - || retlen != len) - { + if (!read_float(s, &retlen, &convertedValue) || retlen != len) { return STATUS_BAD_NUMBER_FORMAT; } if (convertedValue < _minValue || convertedValue > _maxValue) { @@ -299,31 +303,38 @@ const char* FloatSetting::getStringValue() { return strval; } -StringSetting::StringSetting(const char *description, type_t type, permissions_t permissions, const char* grblName, const char* name, const char* defVal, int min, int max, bool (*checker)(char *)) - : Setting(description, type, permissions, grblName, name, checker) -{ +StringSetting::StringSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + const char* defVal, + int min, + int max, + bool (*checker)(char*)) : + Setting(description, type, permissions, grblName, name, checker) { _defaultValue = defVal; _currentValue = defVal; - _minLength = min; - _maxLength = max; - }; + _minLength = min; + _maxLength = max; +}; void StringSetting::load() { - size_t len = 0; + size_t len = 0; esp_err_t err = nvs_get_str(_handle, _keyName, NULL, &len); - if(err) { - _storedValue = _defaultValue; + if (err) { + _storedValue = _defaultValue; _currentValue = _defaultValue; return; } char buf[len]; err = nvs_get_str(_handle, _keyName, buf, &len); if (err) { - _storedValue = _defaultValue; + _storedValue = _defaultValue; _currentValue = _defaultValue; return; } - _storedValue = String(buf); + _storedValue = String(buf); _currentValue = _storedValue; } @@ -341,7 +352,7 @@ err_t StringSetting::setStringValue(char* s) { if (err_t err = check(s)) { return err; } - _currentValue = s; + _currentValue = s; if (_storedValue != _currentValue) { if (_currentValue == _defaultValue) { nvs_erase_key(_handle, _keyName); @@ -358,41 +369,37 @@ err_t StringSetting::setStringValue(char* s) { const char* StringSetting::getStringValue() { // If the string is a password do not display it - if (_checker && - ( - #ifdef ENABLE_WIFI - _checker == (bool (*)(char *))WiFiConfig::isPasswordValid - || - #endif - _checker == (bool (*)(char *))COMMANDS::isLocalPasswordValid - )) { + if (_checker && ( +#ifdef ENABLE_WIFI + _checker == (bool (*)(char*))WiFiConfig::isPasswordValid || +#endif + _checker == (bool (*)(char*))COMMANDS::isLocalPasswordValid)) { return "******"; } return _currentValue.c_str(); } -void StringSetting::addWebui(JSONencoder *j) { +void StringSetting::addWebui(JSONencoder* j) { if (!getDescription()) { return; } - j->begin_webui( - getName(), getDescription(), "S", getStringValue(), _minLength, _maxLength); + j->begin_webui(getName(), getDescription(), "S", getStringValue(), _minLength, _maxLength); j->end_object(); } -typedef std::map enum_opt_t; +typedef std::map enum_opt_t; -EnumSetting::EnumSetting(const char *description, type_t type, permissions_t permissions, const char* grblName, const char* name, int8_t defVal, enum_opt_t *opts) +EnumSetting::EnumSetting( + const char* description, type_t type, permissions_t permissions, const char* grblName, const char* name, int8_t defVal, enum_opt_t* opts) // No checker function because enumerations have an exact set of value - : Setting(description, type, permissions, grblName, name, NULL) - , _defaultValue(defVal) - , _options(opts) -{ } + : + Setting(description, type, permissions, grblName, name, NULL), + _defaultValue(defVal), _options(opts) {} void EnumSetting::load() { esp_err_t err = nvs_get_i8(_handle, _keyName, &_storedValue); if (err) { - _storedValue = -1; + _storedValue = -1; _currentValue = _defaultValue; } else { _currentValue = _storedValue; @@ -411,7 +418,7 @@ void EnumSetting::setDefault() { // This is necessary for WebUI, which uses the number // for setting. err_t EnumSetting::setStringValue(char* s) { - s = trim(s); + s = trim(s); enum_opt_t::iterator it = _options->find(s); if (it == _options->end()) { // If we don't find the value in keys, look for it in the numeric values @@ -420,7 +427,7 @@ err_t EnumSetting::setStringValue(char* s) { if (!s || !*s) { return STATUS_BAD_NUMBER_FORMAT; } - char *endptr; + char* endptr; uint8_t num = strtol(s, &endptr, 10); // Disallow non-numeric characters in string if (*endptr) { @@ -450,9 +457,7 @@ err_t EnumSetting::setStringValue(char* s) { } const char* EnumSetting::getStringValue() { - for (enum_opt_t::iterator it = _options->begin(); - it != _options->end(); - it++) { + for (enum_opt_t::iterator it = _options->begin(); it != _options->end(); it++) { if (it->second == _currentValue) { return it->first; } @@ -460,32 +465,35 @@ const char* EnumSetting::getStringValue() { return "???"; } -void EnumSetting::addWebui(JSONencoder *j) { +void EnumSetting::addWebui(JSONencoder* j) { if (!getDescription()) { - return; + return; } j->begin_webui(getName(), getDescription(), "B", String(get()).c_str()); j->begin_array("O"); - for (enum_opt_t::iterator it = _options->begin(); - it != _options->end(); - it++) { + for (enum_opt_t::iterator it = _options->begin(); it != _options->end(); it++) { j->begin_object(); j->member(it->first, it->second); j->end_object(); - } + } j->end_array(); j->end_object(); } -FlagSetting::FlagSetting(const char *description, type_t type, permissions_t permissions, const char * grblName, const char* name, bool defVal, bool (*checker)(char *) = NULL) : +FlagSetting::FlagSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + bool defVal, + bool (*checker)(char*) = NULL) : Setting(description, type, permissions, grblName, name, checker), - _defaultValue(defVal) -{ } + _defaultValue(defVal) {} void FlagSetting::load() { esp_err_t err = nvs_get_i8(_handle, _keyName, &_storedValue); if (err) { - _storedValue = -1; // Neither well-formed false (0) nor true (1) + _storedValue = -1; // Neither well-formed false (0) nor true (1) _currentValue = _defaultValue; } else { _currentValue = !!_storedValue; @@ -499,12 +507,9 @@ void FlagSetting::setDefault() { } err_t FlagSetting::setStringValue(char* s) { - s = trim(s); - _currentValue = (strcasecmp(s, "on") == 0) - || (strcasecmp(s, "true") == 0) - || (strcasecmp(s, "enabled") == 0) - || (strcasecmp(s, "yes") == 0) - || (strcasecmp(s, "1") == 0); + s = trim(s); + _currentValue = (strcasecmp(s, "on") == 0) || (strcasecmp(s, "true") == 0) || (strcasecmp(s, "enabled") == 0) || + (strcasecmp(s, "yes") == 0) || (strcasecmp(s, "1") == 0); // _storedValue is -1, 0, or 1 // _currentValue is 0 or 1 if (_storedValue != (int8_t)_currentValue) { @@ -526,18 +531,27 @@ const char* FlagSetting::getCompatibleValue() { return get() ? "1" : "0"; } - #include -IPaddrSetting::IPaddrSetting(const char *description, type_t type, permissions_t permissions, const char * grblName, const char* name, uint32_t defVal, bool (*checker)(char *) = NULL) - : Setting(description, type, permissions, grblName, name, checker) // There are no GRBL IP settings. - , _defaultValue(defVal) - , _currentValue(defVal) -{ } +IPaddrSetting::IPaddrSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + uint32_t defVal, + bool (*checker)(char*) = NULL) : + Setting(description, type, permissions, grblName, name, checker) // There are no GRBL IP settings. + , + _defaultValue(defVal), _currentValue(defVal) {} -IPaddrSetting::IPaddrSetting(const char *description, type_t type, permissions_t permissions, const char * grblName, const char* name, const char *defVal, bool (*checker)(char *) = NULL) - : Setting(description, type, permissions, grblName, name, checker) -{ +IPaddrSetting::IPaddrSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + const char* defVal, + bool (*checker)(char*) = NULL) : + Setting(description, type, permissions, grblName, name, checker) { IPAddress ipaddr; if (ipaddr.fromString(defVal)) { _defaultValue = ipaddr; @@ -548,9 +562,9 @@ IPaddrSetting::IPaddrSetting(const char *description, type_t type, permissions_t } void IPaddrSetting::load() { - esp_err_t err = nvs_get_i32(_handle, _keyName, (int32_t *)&_storedValue); + esp_err_t err = nvs_get_i32(_handle, _keyName, (int32_t*)&_storedValue); if (err) { - _storedValue = 0x000000ff; // Unreasonable value for any IP thing + _storedValue = 0x000000ff; // Unreasonable value for any IP thing _currentValue = _defaultValue; } else { _currentValue = _storedValue; @@ -589,21 +603,19 @@ err_t IPaddrSetting::setStringValue(char* s) { const char* IPaddrSetting::getStringValue() { static String s; - IPAddress ipaddr(get()); + IPAddress ipaddr(get()); s = ipaddr.toString(); return s.c_str(); } -void IPaddrSetting::addWebui(JSONencoder *j) { +void IPaddrSetting::addWebui(JSONencoder* j) { if (getDescription()) { j->begin_webui(getName(), getDescription(), "A", getStringValue()); j->end_object(); } } - AxisSettings::AxisSettings(const char *axisName) : - name(axisName) -{} +AxisSettings::AxisSettings(const char* axisName) : name(axisName) {} err_t GrblCommand::action(char* value, auth_t auth_type, ESPResponseStream* out) { if (sys.state & _disallowedStates) { diff --git a/Grbl_Esp32/SettingsClass.h b/Grbl_Esp32/SettingsClass.h index 3a1491a6..467839ec 100644 --- a/Grbl_Esp32/SettingsClass.h +++ b/Grbl_Esp32/SettingsClass.h @@ -39,35 +39,36 @@ typedef uint8_t axis_t; class Word { protected: - const char* _description; - const char* _grblName; - const char* _fullName; - type_t _type; + const char* _description; + const char* _grblName; + const char* _fullName; + type_t _type; permissions_t _permissions; + public: - Word(type_t type, permissions_t permissions, const char *description, const char * grblName, const char* fullName); - type_t getType() { return _type; } + Word(type_t type, permissions_t permissions, const char* description, const char* grblName, const char* fullName); + type_t getType() { return _type; } permissions_t getPermissions() { return _permissions; } - const char* getName() { return _fullName; } - const char* getGrblName() { return _grblName; } - const char* getDescription() { return _description; } + const char* getName() { return _fullName; } + const char* getGrblName() { return _grblName; } + const char* getDescription() { return _description; } }; class Command : public Word { protected: - Command *link; // linked list of setting objects + Command* link; // linked list of setting objects public: static Command* List; - Command* next() { return link; } + Command* next() { return link; } ~Command() {} - Command(const char *description, type_t type, permissions_t permissions, const char * grblName, const char* fullName); + Command(const char* description, type_t type, permissions_t permissions, const char* grblName, const char* fullName); // The default implementation of addWebui() does nothing. // Derived classes may override it to do something. - virtual void addWebui(JSONencoder *) {}; + virtual void addWebui(JSONencoder*) {}; - virtual err_t action(char* value, auth_t auth_level, ESPResponseStream* out) =0; + virtual err_t action(char* value, auth_t auth_level, ESPResponseStream* out) = 0; }; class Setting : public Word { @@ -75,24 +76,24 @@ private: protected: static nvs_handle _handle; // group_t _group; - axis_t _axis = NO_AXIS; - Setting *link; // linked list of setting objects + axis_t _axis = NO_AXIS; + Setting* link; // linked list of setting objects - bool (*_checker)(char *); + bool (*_checker)(char*); const char* _keyName; -public: - static void init(); - static Setting* List; - Setting* next() { return link; } - err_t check(char *s); +public: + static void init(); + static Setting* List; + Setting* next() { return link; } + + err_t check(char* s); static err_t report_nvs_stats(const char* value, auth_t auth_level, ESPResponseStream* out) { nvs_stats_t stats; if (err_t err = nvs_get_stats(NULL, &stats)) return err; - grbl_sendf(out->client(), "[MSG: NVS Used: %d Free: %d Total: %d]\r\n", - stats.used_entries, stats.free_entries, stats.total_entries); + grbl_sendf(out->client(), "[MSG: NVS Used: %d Free: %d Total: %d]\r\n", stats.used_entries, stats.free_entries, stats.total_entries); #if 0 // The SDK we use does not have this yet nvs_iterator_t it = nvs_entry_find(NULL, NULL, NVS_TYPE_ANY); while (it != NULL) { @@ -113,9 +114,9 @@ public: ~Setting() {} // Setting(const char *description, group_t group, const char * grblName, const char* fullName, bool (*checker)(char *)); - Setting(const char *description, type_t type, permissions_t permissions, const char * grblName, const char* fullName, bool (*checker)(char *)); + Setting(const char* description, type_t type, permissions_t permissions, const char* grblName, const char* fullName, bool (*checker)(char*)); axis_t getAxis() { return _axis; } - void setAxis(axis_t axis) { _axis = axis; } + void setAxis(axis_t axis) { _axis = axis; } // load() reads the backing store to get the current // value of the setting. This could be slow so it @@ -125,11 +126,11 @@ public: // The default implementation of addWebui() does nothing. // Derived classes may override it to do something. - virtual void addWebui(JSONencoder *) {}; + virtual void addWebui(JSONencoder*) {}; - virtual err_t setStringValue(char* value) =0; - err_t setStringValue(String s) { return setStringValue(s.c_str()); } - virtual const char* getStringValue() =0; + virtual err_t setStringValue(char* value) = 0; + err_t setStringValue(String s) { return setStringValue(s.c_str()); } + virtual const char* getStringValue() = 0; virtual const char* getCompatibleValue() { return getStringValue(); } }; @@ -142,19 +143,33 @@ private: int32_t _maxValue; public: - IntSetting(const char *description, type_t type, permissions_t permissions, const char* grblName, const char* name, int32_t defVal, int32_t minVal, int32_t maxVal, bool (*checker)(char *)); + IntSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + int32_t defVal, + int32_t minVal, + int32_t maxVal, + bool (*checker)(char*)); - IntSetting(type_t type, permissions_t permissions, const char* grblName, const char* name, int32_t defVal, int32_t minVal, int32_t maxVal, bool (*checker)(char *) = NULL) - : IntSetting(NULL, type, permissions, grblName, name, defVal, minVal, maxVal, checker) - { } + IntSetting(type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + int32_t defVal, + int32_t minVal, + int32_t maxVal, + bool (*checker)(char*) = NULL) : + IntSetting(NULL, type, permissions, grblName, name, defVal, minVal, maxVal, checker) {} - void load(); - void setDefault(); - void addWebui(JSONencoder *); - err_t setStringValue(char* value); + void load(); + void setDefault(); + void addWebui(JSONencoder*); + err_t setStringValue(char* value); const char* getStringValue(); - int32_t get() { return _currentValue; } + int32_t get() { return _currentValue; } }; class AxisMaskSetting : public Setting { @@ -164,20 +179,26 @@ private: int32_t _storedValue; public: - AxisMaskSetting(const char *description, type_t type, permissions_t permissions, const char* grblName, const char* name, int32_t defVal, bool (*checker)(char *)); + AxisMaskSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + int32_t defVal, + bool (*checker)(char*)); - AxisMaskSetting(type_t type, permissions_t permissions, const char* grblName, const char* name, int32_t defVal, bool (*checker)(char *) = NULL) - : AxisMaskSetting(NULL, type, permissions, grblName, name, defVal, checker) - { } + AxisMaskSetting( + type_t type, permissions_t permissions, const char* grblName, const char* name, int32_t defVal, bool (*checker)(char*) = NULL) : + AxisMaskSetting(NULL, type, permissions, grblName, name, defVal, checker) {} - void load(); - void setDefault(); - void addWebui(JSONencoder *); - err_t setStringValue(char* value); + void load(); + void setDefault(); + void addWebui(JSONencoder*); + err_t setStringValue(char* value); const char* getCompatibleValue(); const char* getStringValue(); - int32_t get() { return _currentValue; } + int32_t get() { return _currentValue; } }; class FloatSetting : public Setting { @@ -187,21 +208,36 @@ private: float _storedValue; float _minValue; float _maxValue; -public: - FloatSetting(const char *description, type_t type, permissions_t permissions, const char* grblName, const char* name, float defVal, float minVal, float maxVal, bool (*checker)(char *)); - FloatSetting(type_t type, permissions_t permissions, const char* grblName, const char* name, float defVal, float minVal, float maxVal, bool (*checker)(char *) = NULL) - : FloatSetting(NULL, type, permissions, grblName, name, defVal, minVal, maxVal, checker) - { } +public: + FloatSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + float defVal, + float minVal, + float maxVal, + bool (*checker)(char*)); + + FloatSetting(type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + float defVal, + float minVal, + float maxVal, + bool (*checker)(char*) = NULL) : + FloatSetting(NULL, type, permissions, grblName, name, defVal, minVal, maxVal, checker) {} void load(); void setDefault(); // There are no Float settings in WebUI - void addWebui(JSONencoder *) {} - err_t setStringValue(char* value); + void addWebui(JSONencoder*) {} + err_t setStringValue(char* value); const char* getStringValue(); - float get() { return _currentValue; } + float get() { return _currentValue; } }; #define MAX_SETTING_STRING 256 @@ -210,76 +246,93 @@ private: String _defaultValue; String _currentValue; String _storedValue; - int _minLength; - int _maxLength; - void _setStoredValue(const char *s); + int _minLength; + int _maxLength; + void _setStoredValue(const char* s); + public: - StringSetting(const char *description, type_t type, permissions_t permissions, const char* grblName, const char* name, const char* defVal, int min, int max, bool (*checker)(char *)); + StringSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + const char* defVal, + int min, + int max, + bool (*checker)(char*)); - StringSetting(type_t type, permissions_t permissions, const char* grblName, const char* name, const char* defVal, bool (*checker)(char *) = NULL) - : StringSetting(NULL, type, permissions, grblName, name, defVal, 0, 0, checker) - { }; + StringSetting( + type_t type, permissions_t permissions, const char* grblName, const char* name, const char* defVal, bool (*checker)(char*) = NULL) : + StringSetting(NULL, type, permissions, grblName, name, defVal, 0, 0, checker) {}; - void load(); - void setDefault(); - void addWebui(JSONencoder *); - err_t setStringValue(char* value); + void load(); + void setDefault(); + void addWebui(JSONencoder*); + err_t setStringValue(char* value); const char* getStringValue(); - const char* get() { return _currentValue.c_str(); } + const char* get() { return _currentValue.c_str(); } }; -struct cmp_str -{ - bool operator()(char const *a, char const *b) const - { - return strcasecmp(a, b) < 0; - } +struct cmp_str { + bool operator()(char const* a, char const* b) const { return strcasecmp(a, b) < 0; } }; -typedef std::map enum_opt_t; +typedef std::map enum_opt_t; class EnumSetting : public Setting { private: - int8_t _defaultValue; - int8_t _storedValue; - int8_t _currentValue; - std::map* _options; + int8_t _defaultValue; + int8_t _storedValue; + int8_t _currentValue; + std::map* _options; + public: - EnumSetting(const char *description, type_t type, permissions_t permissions, const char* grblName, const char* name, int8_t defVal, enum_opt_t* opts); + EnumSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + int8_t defVal, + enum_opt_t* opts); EnumSetting(type_t type, permissions_t permissions, const char* grblName, const char* name, int8_t defVal, enum_opt_t* opts) : - EnumSetting(NULL, type, permissions, grblName, name, defVal, opts) - { } + EnumSetting(NULL, type, permissions, grblName, name, defVal, opts) {} - void load(); - void setDefault(); - void addWebui(JSONencoder *); - err_t setStringValue(char* value); + void load(); + void setDefault(); + void addWebui(JSONencoder*); + err_t setStringValue(char* value); const char* getStringValue(); - int8_t get() { return _currentValue; } + int8_t get() { return _currentValue; } }; class FlagSetting : public Setting { private: - bool _defaultValue; + bool _defaultValue; int8_t _storedValue; - bool _currentValue; + bool _currentValue; + public: - FlagSetting(const char *description, type_t type, permissions_t permissions, const char* grblName, const char* name, bool defVal, bool (*checker)(char *)); - FlagSetting(type_t type, permissions_t permissions, const char* grblName, const char* name, bool defVal, bool (*checker)(char *) = NULL) - : FlagSetting(NULL, type, permissions, grblName, name, defVal, checker) - { } + FlagSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + bool defVal, + bool (*checker)(char*)); + FlagSetting(type_t type, permissions_t permissions, const char* grblName, const char* name, bool defVal, bool (*checker)(char*) = NULL) : + FlagSetting(NULL, type, permissions, grblName, name, defVal, checker) {} void load(); void setDefault(); // There are no Flag settings in WebUI // The booleans are expressed as Enums - void addWebui(JSONencoder *) {} - err_t setStringValue(char* value); + void addWebui(JSONencoder*) {} + err_t setStringValue(char* value); const char* getCompatibleValue(); const char* getStringValue(); - bool get() { return _currentValue; } + bool get() { return _currentValue; } }; class IPaddrSetting : public Setting { @@ -289,64 +342,83 @@ private: uint32_t _storedValue; public: - IPaddrSetting(const char *description, type_t type, permissions_t permissions, const char * grblName, const char* name, uint32_t defVal, bool (*checker)(char *)); - IPaddrSetting(const char *description, type_t type, permissions_t permissions, const char * grblName, const char* name, const char *defVal, bool (*checker)(char *)); + IPaddrSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + uint32_t defVal, + bool (*checker)(char*)); + IPaddrSetting(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + const char* defVal, + bool (*checker)(char*)); - void load(); - void setDefault(); - void addWebui(JSONencoder *); - err_t setStringValue(char* value); + void load(); + void setDefault(); + void addWebui(JSONencoder*); + err_t setStringValue(char* value); const char* getStringValue(); - uint32_t get() { return _currentValue; } + uint32_t get() { return _currentValue; } }; class AxisSettings { public: - const char* name; - FloatSetting *steps_per_mm; - FloatSetting *max_rate; - FloatSetting *acceleration; - FloatSetting *max_travel; - FloatSetting *run_current; - FloatSetting *hold_current; - IntSetting *microsteps; - IntSetting *stallguard; + const char* name; + FloatSetting* steps_per_mm; + FloatSetting* max_rate; + FloatSetting* acceleration; + FloatSetting* max_travel; + FloatSetting* run_current; + FloatSetting* hold_current; + IntSetting* microsteps; + IntSetting* stallguard; - AxisSettings(const char *axisName); + AxisSettings(const char* axisName); }; class WebCommand : public Command { - private: - err_t (*_action)(char *, auth_t); - const char* password; - public: - WebCommand(const char* description, type_t type, permissions_t permissions, const char * grblName, const char* name, err_t (*action)(char *, auth_t)) : +private: + err_t (*_action)(char*, auth_t); + const char* password; + +public: + WebCommand(const char* description, + type_t type, + permissions_t permissions, + const char* grblName, + const char* name, + err_t (*action)(char*, auth_t)) : Command(description, type, permissions, grblName, name), - _action(action) - {} + _action(action) {} err_t action(char* value, auth_t auth_level, ESPResponseStream* response); }; enum : uint8_t { - ANY_STATE = 0, - IDLE_OR_ALARM = 0xff & ~STATE_ALARM, - IDLE_OR_JOG = 0xff & ~STATE_JOG, + ANY_STATE = 0, + IDLE_OR_ALARM = 0xff & ~STATE_ALARM, + IDLE_OR_JOG = 0xff & ~STATE_JOG, NOT_CYCLE_OR_HOLD = STATE_CYCLE | STATE_HOLD, }; class GrblCommand : public Command { - private: - err_t (*_action)(const char *, auth_t, ESPResponseStream*); - uint8_t _disallowedStates; - public: - GrblCommand(const char * grblName, const char* name, err_t (*action)(const char*, auth_t, ESPResponseStream*), uint8_t disallowedStates, permissions_t auth) - : Command(NULL, GRBLCMD, auth, grblName, name) - , _action(action) - , _disallowedStates(disallowedStates) - {} +private: + err_t (*_action)(const char*, auth_t, ESPResponseStream*); + uint8_t _disallowedStates; - GrblCommand(const char * grblName, const char* name, err_t (*action)(const char*, auth_t, ESPResponseStream*), uint8_t disallowedStates) - : GrblCommand(grblName, name, action, disallowedStates, WG) - {} +public: + GrblCommand(const char* grblName, + const char* name, + err_t (*action)(const char*, auth_t, ESPResponseStream*), + uint8_t disallowedStates, + permissions_t auth) : + Command(NULL, GRBLCMD, auth, grblName, name), + _action(action), _disallowedStates(disallowedStates) {} + + GrblCommand(const char* grblName, const char* name, err_t (*action)(const char*, auth_t, ESPResponseStream*), uint8_t disallowedStates) : + GrblCommand(grblName, name, action, disallowedStates, WG) {} err_t action(char* value, auth_t auth_level, ESPResponseStream* response); }; diff --git a/Grbl_Esp32/SettingsDefinitions.cpp b/Grbl_Esp32/SettingsDefinitions.cpp index 9c10c1a2..7bd18ebf 100644 --- a/Grbl_Esp32/SettingsDefinitions.cpp +++ b/Grbl_Esp32/SettingsDefinitions.cpp @@ -28,7 +28,7 @@ FlagSetting* homing_enable; FlagSetting* laser_mode; // TODO Settings - also need to call my_spindle->init; -IntSetting* status_mask; +IntSetting* status_mask; FloatSetting* junction_deviation; FloatSetting* arc_tolerance; @@ -45,19 +45,21 @@ FloatSetting* spindle_delay_spindown; FloatSetting* spindle_pwm_off_value; FloatSetting* spindle_pwm_min_value; FloatSetting* spindle_pwm_max_value; -IntSetting* spindle_pwm_bit_precision; +IntSetting* spindle_pwm_bit_precision; EnumSetting* spindle_type; enum_opt_t spindleTypes = { - { "NONE", SPINDLE_TYPE_NONE, }, - { "PWM", SPINDLE_TYPE_PWM, }, - { "RELAY", SPINDLE_TYPE_RELAY, }, - { "LASER", SPINDLE_TYPE_LASER, }, - { "DAC", SPINDLE_TYPE_DAC, }, - { "HUANYANG", SPINDLE_TYPE_HUANYANG, }, - { "BESC", SPINDLE_TYPE_BESC, }, - { "10V", SPINDLE_TYPE_10V, }, + // clang-format off + { "NONE", SPINDLE_TYPE_NONE }, + { "PWM", SPINDLE_TYPE_PWM }, + { "RELAY", SPINDLE_TYPE_RELAY }, + { "LASER", SPINDLE_TYPE_LASER }, + { "DAC", SPINDLE_TYPE_DAC }, + { "HUANYANG", SPINDLE_TYPE_HUANYANG }, + { "BESC", SPINDLE_TYPE_BESC }, + { "10V", SPINDLE_TYPE_10V }, + // clang-format on }; AxisSettings* x_axis_settings; @@ -71,89 +73,75 @@ AxisSettings* axis_settings[MAX_N_AXIS]; typedef struct { const char* name; - float steps_per_mm; - float max_rate; - float acceleration; - float max_travel; - float run_current; - float hold_current; - uint16_t microsteps; - uint16_t stallguard; + float steps_per_mm; + float max_rate; + float acceleration; + float max_travel; + float run_current; + float hold_current; + uint16_t microsteps; + uint16_t stallguard; } axis_defaults_t; -axis_defaults_t axis_defaults[] = { - { - "X", - DEFAULT_X_STEPS_PER_MM, - DEFAULT_X_MAX_RATE, - DEFAULT_X_ACCELERATION, - DEFAULT_X_MAX_TRAVEL, - DEFAULT_X_CURRENT, - DEFAULT_X_HOLD_CURRENT, - DEFAULT_X_MICROSTEPS, - DEFAULT_X_STALLGUARD - }, - { - "Y", - DEFAULT_Y_STEPS_PER_MM, - DEFAULT_Y_MAX_RATE, - DEFAULT_Y_ACCELERATION, - DEFAULT_Y_MAX_TRAVEL, - DEFAULT_Y_CURRENT, - DEFAULT_Y_HOLD_CURRENT, - DEFAULT_Y_MICROSTEPS, - DEFAULT_Y_STALLGUARD - }, - { - "Z", - DEFAULT_Z_STEPS_PER_MM, - DEFAULT_Z_MAX_RATE, - DEFAULT_Z_ACCELERATION, - DEFAULT_Z_MAX_TRAVEL, - DEFAULT_Z_CURRENT, - DEFAULT_Z_HOLD_CURRENT, - DEFAULT_Z_MICROSTEPS, - DEFAULT_Z_STALLGUARD - }, - { - "A", - DEFAULT_A_STEPS_PER_MM, - DEFAULT_A_MAX_RATE, - DEFAULT_A_ACCELERATION, - DEFAULT_A_MAX_TRAVEL, - DEFAULT_A_CURRENT, - DEFAULT_A_HOLD_CURRENT, - DEFAULT_A_MICROSTEPS, - DEFAULT_A_STALLGUARD - }, - { - "B", - DEFAULT_B_STEPS_PER_MM, - DEFAULT_B_MAX_RATE, - DEFAULT_B_ACCELERATION, - DEFAULT_B_MAX_TRAVEL, - DEFAULT_B_CURRENT, - DEFAULT_B_HOLD_CURRENT, - DEFAULT_B_MICROSTEPS, - DEFAULT_B_STALLGUARD - }, - { - "C", - DEFAULT_C_STEPS_PER_MM, - DEFAULT_C_MAX_RATE, - DEFAULT_C_ACCELERATION, - DEFAULT_C_MAX_TRAVEL, - DEFAULT_C_CURRENT, - DEFAULT_C_HOLD_CURRENT, - DEFAULT_C_MICROSTEPS, - DEFAULT_C_STALLGUARD - } -}; +axis_defaults_t axis_defaults[] = { { "X", + DEFAULT_X_STEPS_PER_MM, + DEFAULT_X_MAX_RATE, + DEFAULT_X_ACCELERATION, + DEFAULT_X_MAX_TRAVEL, + DEFAULT_X_CURRENT, + DEFAULT_X_HOLD_CURRENT, + DEFAULT_X_MICROSTEPS, + DEFAULT_X_STALLGUARD }, + { "Y", + DEFAULT_Y_STEPS_PER_MM, + DEFAULT_Y_MAX_RATE, + DEFAULT_Y_ACCELERATION, + DEFAULT_Y_MAX_TRAVEL, + DEFAULT_Y_CURRENT, + DEFAULT_Y_HOLD_CURRENT, + DEFAULT_Y_MICROSTEPS, + DEFAULT_Y_STALLGUARD }, + { "Z", + DEFAULT_Z_STEPS_PER_MM, + DEFAULT_Z_MAX_RATE, + DEFAULT_Z_ACCELERATION, + DEFAULT_Z_MAX_TRAVEL, + DEFAULT_Z_CURRENT, + DEFAULT_Z_HOLD_CURRENT, + DEFAULT_Z_MICROSTEPS, + DEFAULT_Z_STALLGUARD }, + { "A", + DEFAULT_A_STEPS_PER_MM, + DEFAULT_A_MAX_RATE, + DEFAULT_A_ACCELERATION, + DEFAULT_A_MAX_TRAVEL, + DEFAULT_A_CURRENT, + DEFAULT_A_HOLD_CURRENT, + DEFAULT_A_MICROSTEPS, + DEFAULT_A_STALLGUARD }, + { "B", + DEFAULT_B_STEPS_PER_MM, + DEFAULT_B_MAX_RATE, + DEFAULT_B_ACCELERATION, + DEFAULT_B_MAX_TRAVEL, + DEFAULT_B_CURRENT, + DEFAULT_B_HOLD_CURRENT, + DEFAULT_B_MICROSTEPS, + DEFAULT_B_STALLGUARD }, + { "C", + DEFAULT_C_STEPS_PER_MM, + DEFAULT_C_MAX_RATE, + DEFAULT_C_ACCELERATION, + DEFAULT_C_MAX_TRAVEL, + DEFAULT_C_CURRENT, + DEFAULT_C_HOLD_CURRENT, + DEFAULT_C_MICROSTEPS, + DEFAULT_C_STALLGUARD } }; // Construct e.g. X_MAX_RATE from axisName "X" and tail "_MAX_RATE" // in dynamically allocated memory that will not be freed. -static const char *makename(const char *axisName, const char *tail) { - char* retval = (char *)malloc(strlen(axisName) + strlen(tail) + 2); +static const char* makename(const char* axisName, const char* tail) { + char* retval = (char*)malloc(strlen(axisName) + strlen(tail) + 2); strcpy(retval, axisName); strcat(retval, "/"); @@ -186,7 +174,6 @@ static bool checkHoldcurrent(char* value) { return true; } - static bool checkStallguardDebugMask(char* val) { motorSettingChanged = true; return true; @@ -207,10 +194,10 @@ void make_settings() { // Create the axis settings in the order that people are // accustomed to seeing. - int axis; + int axis; axis_defaults_t* def; for (axis = 0; axis < N_AXIS; axis++) { - def = &axis_defaults[axis]; + def = &axis_defaults[axis]; axis_settings[axis] = new AxisSettings(def->name); } x_axis_settings = axis_settings[X_AXIS]; @@ -220,50 +207,56 @@ void make_settings() { b_axis_settings = axis_settings[B_AXIS]; c_axis_settings = axis_settings[C_AXIS]; for (axis = N_AXIS - 1; axis >= 0; axis--) { - def = &axis_defaults[axis]; - auto setting = new IntSetting(EXTENDED, WG, makeGrblName(axis, 170), makename(def->name, "StallGuard"), def->stallguard, -64, 63, checkStallguard); + def = &axis_defaults[axis]; + auto setting = new IntSetting( + EXTENDED, WG, makeGrblName(axis, 170), makename(def->name, "StallGuard"), def->stallguard, -64, 63, checkStallguard); setting->setAxis(axis); axis_settings[axis]->stallguard = setting; } for (axis = N_AXIS - 1; axis >= 0; axis--) { - def = &axis_defaults[axis]; - auto setting = new IntSetting(EXTENDED, WG, makeGrblName(axis, 160), makename(def->name, "Microsteps"), def->microsteps, 0, 256, checkMicrosteps); + def = &axis_defaults[axis]; + auto setting = new IntSetting( + EXTENDED, WG, makeGrblName(axis, 160), makename(def->name, "Microsteps"), def->microsteps, 0, 256, checkMicrosteps); setting->setAxis(axis); axis_settings[axis]->microsteps = setting; } for (axis = N_AXIS - 1; axis >= 0; axis--) { - def = &axis_defaults[axis]; - auto setting = new FloatSetting(EXTENDED, WG, makeGrblName(axis, 150), makename(def->name, "Current/Hold"), def->hold_current, 0.05, 20.0, checkHoldcurrent); // Amps + def = &axis_defaults[axis]; + auto setting = new FloatSetting( + EXTENDED, WG, makeGrblName(axis, 150), makename(def->name, "Current/Hold"), def->hold_current, 0.05, 20.0, checkHoldcurrent); // Amps setting->setAxis(axis); axis_settings[axis]->hold_current = setting; } for (axis = N_AXIS - 1; axis >= 0; axis--) { - def = &axis_defaults[axis]; - auto setting = new FloatSetting(EXTENDED, WG, makeGrblName(axis, 140), makename(def->name, "Current/Run"), def->run_current, 0.0, 20.0, checkRunCurrent); // Amps + def = &axis_defaults[axis]; + auto setting = new FloatSetting( + EXTENDED, WG, makeGrblName(axis, 140), makename(def->name, "Current/Run"), def->run_current, 0.0, 20.0, checkRunCurrent); // Amps setting->setAxis(axis); axis_settings[axis]->run_current = setting; } for (axis = N_AXIS - 1; axis >= 0; axis--) { - def = &axis_defaults[axis]; + def = &axis_defaults[axis]; auto setting = new FloatSetting(GRBL, WG, makeGrblName(axis, 130), makename(def->name, "MaxTravel"), def->max_travel, 1.0, 100000.0); setting->setAxis(axis); axis_settings[axis]->max_travel = setting; } for (axis = N_AXIS - 1; axis >= 0; axis--) { def = &axis_defaults[axis]; - auto setting = new FloatSetting(GRBL, WG, makeGrblName(axis, 120), makename(def->name, "Acceleration"), def->acceleration, 1.0, 100000.0); + auto setting = + new FloatSetting(GRBL, WG, makeGrblName(axis, 120), makename(def->name, "Acceleration"), def->acceleration, 1.0, 100000.0); setting->setAxis(axis); axis_settings[axis]->acceleration = setting; } for (axis = N_AXIS - 1; axis >= 0; axis--) { - def = &axis_defaults[axis]; + def = &axis_defaults[axis]; auto setting = new FloatSetting(GRBL, WG, makeGrblName(axis, 110), makename(def->name, "MaxRate"), def->max_rate, 1.0, 100000.0); setting->setAxis(axis); axis_settings[axis]->max_rate = setting; } for (axis = N_AXIS - 1; axis >= 0; axis--) { def = &axis_defaults[axis]; - auto setting = new FloatSetting(GRBL, WG, makeGrblName(axis, 100), makename(def->name, "StepsPerMm"), def->steps_per_mm, 1.0, 100000.0); + auto setting = + new FloatSetting(GRBL, WG, makeGrblName(axis, 100), makename(def->name, "StepsPerMm"), def->steps_per_mm, 1.0, 100000.0); setting->setAxis(axis); axis_settings[axis]->steps_per_mm = setting; } @@ -271,10 +264,11 @@ void make_settings() { // Spindle Settings spindle_pwm_max_value = new FloatSetting(EXTENDED, WG, "36", "Spindle/PWM/Max", DEFAULT_SPINDLE_MAX_VALUE, 0.0, 100.0); spindle_pwm_min_value = new FloatSetting(EXTENDED, WG, "35", "Spindle/PWM/Min", DEFAULT_SPINDLE_MIN_VALUE, 0.0, 100.0); - spindle_pwm_off_value = new FloatSetting(EXTENDED, WG, "34", "Spindle/PWM/Off", DEFAULT_SPINDLE_OFF_VALUE, 0.0, 100.0); // these are percentages + spindle_pwm_off_value = + new FloatSetting(EXTENDED, WG, "34", "Spindle/PWM/Off", DEFAULT_SPINDLE_OFF_VALUE, 0.0, 100.0); // these are percentages // IntSetting spindle_pwm_bit_precision(EXTENDED, WG, "Spindle/PWM/Precision", DEFAULT_SPINDLE_BIT_PRECISION, 1, 16); - spindle_pwm_freq = new FloatSetting(EXTENDED, WG, "33", "Spindle/PWM/Frequency", DEFAULT_SPINDLE_FREQ, 0, 100000); - spindle_delay_spinup = new FloatSetting(EXTENDED, WG, NULL, "Spindle/Delay/SpinUp", DEFAULT_SPINDLE_DELAY_SPINUP, 0, 30); + spindle_pwm_freq = new FloatSetting(EXTENDED, WG, "33", "Spindle/PWM/Frequency", DEFAULT_SPINDLE_FREQ, 0, 100000); + spindle_delay_spinup = new FloatSetting(EXTENDED, WG, NULL, "Spindle/Delay/SpinUp", DEFAULT_SPINDLE_DELAY_SPINUP, 0, 30); spindle_delay_spindown = new FloatSetting(EXTENDED, WG, NULL, "Spindle/Delay/SpinDown", DEFAULT_SPINDLE_DELAY_SPINUP, 0, 30); // GRBL Non-numbered settings @@ -287,9 +281,8 @@ void make_settings() { rpm_min = new FloatSetting(GRBL, WG, "31", "GCode/MinS", DEFAULT_SPINDLE_RPM_MIN, 0, 100000); rpm_max = new FloatSetting(GRBL, WG, "30", "GCode/MaxS", DEFAULT_SPINDLE_RPM_MAX, 0, 100000); - - homing_pulloff = new FloatSetting(GRBL, WG, "27", "Homing/Pulloff", DEFAULT_HOMING_PULLOFF, 0, 1000); - homing_debounce = new FloatSetting(GRBL, WG, "26", "Homing/Debounce", DEFAULT_HOMING_DEBOUNCE_DELAY, 0, 10000); + homing_pulloff = new FloatSetting(GRBL, WG, "27", "Homing/Pulloff", DEFAULT_HOMING_PULLOFF, 0, 1000); + homing_debounce = new FloatSetting(GRBL, WG, "26", "Homing/Debounce", DEFAULT_HOMING_DEBOUNCE_DELAY, 0, 10000); homing_seek_rate = new FloatSetting(GRBL, WG, "25", "Homing/Seek", DEFAULT_HOMING_SEEK_RATE, 0, 10000); homing_feed_rate = new FloatSetting(GRBL, WG, "24", "Homing/Feed", DEFAULT_HOMING_FEED_RATE, 0, 10000); @@ -304,17 +297,17 @@ void make_settings() { report_inches = new FlagSetting(GRBL, WG, "13", "Report/Inches", DEFAULT_REPORT_INCHES); // TODO Settings - also need to clear, but not set, soft_limits - arc_tolerance = new FloatSetting(GRBL, WG, "12", "GCode/ArcTolerance", DEFAULT_ARC_TOLERANCE, 0, 1); + arc_tolerance = new FloatSetting(GRBL, WG, "12", "GCode/ArcTolerance", DEFAULT_ARC_TOLERANCE, 0, 1); junction_deviation = new FloatSetting(GRBL, WG, "11", "GCode/JunctionDeviation", DEFAULT_JUNCTION_DEVIATION, 0, 10); - status_mask = new IntSetting(GRBL, WG, "10", "Report/Status", DEFAULT_STATUS_REPORT_MASK, 0, 2); + status_mask = new IntSetting(GRBL, WG, "10", "Report/Status", DEFAULT_STATUS_REPORT_MASK, 0, 2); - probe_invert = new FlagSetting(GRBL, WG, "6", "Probe/Invert", DEFAULT_INVERT_PROBE_PIN); - limit_invert = new FlagSetting(GRBL, WG, "5", "Limits/Invert", DEFAULT_INVERT_LIMIT_PINS); - step_enable_invert = new FlagSetting(GRBL, WG, "4", "Stepper/EnableInvert", DEFAULT_INVERT_ST_ENABLE); - dir_invert_mask = new AxisMaskSetting(GRBL, WG, "3", "Stepper/DirInvert", DEFAULT_DIRECTION_INVERT_MASK); - step_invert_mask = new AxisMaskSetting(GRBL, WG, "2", "Stepper/StepInvert", DEFAULT_STEPPING_INVERT_MASK); + probe_invert = new FlagSetting(GRBL, WG, "6", "Probe/Invert", DEFAULT_INVERT_PROBE_PIN); + limit_invert = new FlagSetting(GRBL, WG, "5", "Limits/Invert", DEFAULT_INVERT_LIMIT_PINS); + step_enable_invert = new FlagSetting(GRBL, WG, "4", "Stepper/EnableInvert", DEFAULT_INVERT_ST_ENABLE); + dir_invert_mask = new AxisMaskSetting(GRBL, WG, "3", "Stepper/DirInvert", DEFAULT_DIRECTION_INVERT_MASK); + step_invert_mask = new AxisMaskSetting(GRBL, WG, "2", "Stepper/StepInvert", DEFAULT_STEPPING_INVERT_MASK); stepper_idle_lock_time = new IntSetting(GRBL, WG, "1", "Stepper/IdleTime", DEFAULT_STEPPER_IDLE_LOCK_TIME, 0, 255); - pulse_microseconds = new IntSetting(GRBL, WG, "0", "Stepper/Pulse", DEFAULT_STEP_PULSE_MICROSECONDS, 3, 1000); - spindle_type = new EnumSetting(NULL, EXTENDED, WG, NULL, "Spindle/Type", SPINDLE_TYPE, &spindleTypes); - stallguard_debug_mask = new AxisMaskSetting(EXTENDED, WG, NULL, "Report/StallGuard", 0, checkStallguardDebugMask); + pulse_microseconds = new IntSetting(GRBL, WG, "0", "Stepper/Pulse", DEFAULT_STEP_PULSE_MICROSECONDS, 3, 1000); + spindle_type = new EnumSetting(NULL, EXTENDED, WG, NULL, "Spindle/Type", SPINDLE_TYPE, &spindleTypes); + stallguard_debug_mask = new AxisMaskSetting(EXTENDED, WG, NULL, "Report/StallGuard", 0, checkStallguardDebugMask); } diff --git a/Grbl_Esp32/SettingsDefinitions.h b/Grbl_Esp32/SettingsDefinitions.h index bd43bf64..4d3efb98 100644 --- a/Grbl_Esp32/SettingsDefinitions.h +++ b/Grbl_Esp32/SettingsDefinitions.h @@ -30,7 +30,7 @@ extern FlagSetting* hard_limits; extern FlagSetting* homing_enable; extern FlagSetting* laser_mode; -extern IntSetting* status_mask; +extern IntSetting* status_mask; extern FloatSetting* junction_deviation; extern FloatSetting* arc_tolerance; @@ -47,7 +47,7 @@ extern FloatSetting* spindle_delay_spindown; extern FloatSetting* spindle_pwm_off_value; extern FloatSetting* spindle_pwm_min_value; extern FloatSetting* spindle_pwm_max_value; -extern IntSetting* spindle_pwm_bit_precision; +extern IntSetting* spindle_pwm_bit_precision; extern EnumSetting* spindle_type; diff --git a/Grbl_Esp32/Spindles/10vSpindle.cpp b/Grbl_Esp32/Spindles/10vSpindle.cpp index d210a26a..60691f28 100644 --- a/Grbl_Esp32/Spindles/10vSpindle.cpp +++ b/Grbl_Esp32/Spindles/10vSpindle.cpp @@ -29,11 +29,8 @@ */ #include "SpindleClass.h" - - -void _10vSpindle :: init() { - - get_pins_and_settings(); // these gets the standard PWM settings, but many need to be changed for BESC +void _10vSpindle ::init() { + get_pins_and_settings(); // these gets the standard PWM settings, but many need to be changed for BESC // a couple more pins not inherited from PWM Spindle #ifdef SPINDLE_FORWARD_PIN @@ -48,14 +45,13 @@ void _10vSpindle :: init() { _reverse_pin = UNDEFINED_PIN; #endif - if (_output_pin == UNDEFINED_PIN) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: BESC output pin not defined"); - return; // We cannot continue without the output pin + return; // We cannot continue without the output pin } - ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, _pwm_precision); // setup the channel - ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin + ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, _pwm_precision); // setup the channel + ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin pinMode(_enable_pin, OUTPUT); pinMode(_direction_pin, OUTPUT); @@ -66,13 +62,12 @@ void _10vSpindle :: init() { config_message(); - is_reversable = true; // these VFDs are always reversable - use_delays = true; - + is_reversable = true; // these VFDs are always reversable + use_delays = true; } // prints the startup message of the spindle config -void _10vSpindle :: config_message() { +void _10vSpindle ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "0-10V spindle Out:%s Enbl:%s, Dir:%s, Fwd:%s, Rev:%s, Freq:%dHz Res:%dbits", @@ -92,7 +87,7 @@ uint32_t _10vSpindle::set_rpm(uint32_t rpm) { return rpm; // apply speed overrides - rpm = rpm * sys.spindle_speed_ovr / 100; // Scale by spindle speed override value (percent) + rpm = rpm * sys.spindle_speed_ovr / 100; // Scale by spindle speed override value (percent) // apply limits limits if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) @@ -130,9 +125,8 @@ void _10vSpindle::set_state(uint8_t state, uint32_t rpm) { */ - uint8_t _10vSpindle::get_state() { - if (_current_pwm_duty == 0 || _output_pin == UNDEFINED_PIN) + if (_current_pwm_duty == 0 || _output_pin == UNDEFINED_PIN) return (SPINDLE_STATE_DISABLE); if (_direction_pin != UNDEFINED_PIN) return digitalRead(_direction_pin) ? SPINDLE_STATE_CW : SPINDLE_STATE_CCW; @@ -147,7 +141,7 @@ void _10vSpindle::stop() { void _10vSpindle::set_enable_pin(bool enable) { //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "_10vSpindle::set_enable_pin"); - if (_off_with_zero_speed && sys.spindle_speed == 0) + if (_off_with_zero_speed && sys.spindle_speed == 0) enable = false; #ifdef INVERT_SPINDLE_ENABLE_PIN @@ -167,6 +161,5 @@ void _10vSpindle::set_spindle_dir_pin(bool Clockwise) { //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "_10vSpindle::set_spindle_dir_pin"); digitalWrite(_direction_pin, Clockwise); digitalWrite(_forward_pin, Clockwise); - digitalWrite(_reverse_pin, ! Clockwise); + digitalWrite(_reverse_pin, !Clockwise); } - diff --git a/Grbl_Esp32/Spindles/BESCSpindle.cpp b/Grbl_Esp32/Spindles/BESCSpindle.cpp index 14d575d7..07033203 100644 --- a/Grbl_Esp32/Spindles/BESCSpindle.cpp +++ b/Grbl_Esp32/Spindles/BESCSpindle.cpp @@ -32,37 +32,35 @@ */ #include "SpindleClass.h" - // don't change these -#define BESC_PWM_FREQ 50.0f // Hz -#define BESC_PWM_BIT_PRECISION 16 // bits -#define BESC_PULSE_PERIOD (1.0 / BESC_PWM_FREQ) +#define BESC_PWM_FREQ 50.0f // Hz +#define BESC_PWM_BIT_PRECISION 16 // bits +#define BESC_PULSE_PERIOD (1.0 / BESC_PWM_FREQ) // Ok to tweak. These are the pulse lengths in seconds // #define them in your machine definition file if you want different values #ifndef BESC_MIN_PULSE_SECS - #define BESC_MIN_PULSE_SECS 0.0009f // in seconds +# define BESC_MIN_PULSE_SECS 0.0009f // in seconds #endif #ifndef BESC_MAX_PULSE_SECS - #define BESC_MAX_PULSE_SECS 0.0022f // in seconds +# define BESC_MAX_PULSE_SECS 0.0022f // in seconds #endif //calculations...don't change -#define BESC_MIN_PULSE_CNT (uint16_t)(BESC_MIN_PULSE_SECS / BESC_PULSE_PERIOD * 65535.0) -#define BESC_MAX_PULSE_CNT (uint16_t)(BESC_MAX_PULSE_SECS / BESC_PULSE_PERIOD * 65535.0) +#define BESC_MIN_PULSE_CNT (uint16_t)(BESC_MIN_PULSE_SECS / BESC_PULSE_PERIOD * 65535.0) +#define BESC_MAX_PULSE_CNT (uint16_t)(BESC_MAX_PULSE_SECS / BESC_PULSE_PERIOD * 65535.0) -void BESCSpindle :: init() { - - get_pins_and_settings(); // these gets the standard PWM settings, but many need to be changed for BESC +void BESCSpindle ::init() { + get_pins_and_settings(); // these gets the standard PWM settings, but many need to be changed for BESC if (_output_pin == UNDEFINED_PIN) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: BESC output pin not defined"); - return; // We cannot continue without the output pin + return; // We cannot continue without the output pin } // override some settings to what is required for a BESC - _pwm_freq = (uint32_t)BESC_PWM_FREQ; + _pwm_freq = (uint32_t)BESC_PWM_FREQ; _pwm_precision = 16; // override these settings @@ -70,8 +68,8 @@ void BESCSpindle :: init() { _pwm_min_value = _pwm_off_value; _pwm_max_value = BESC_MAX_PULSE_CNT; - ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, _pwm_precision); // setup the channel - ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin + ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, _pwm_precision); // setup the channel + ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin pinMode(_enable_pin, OUTPUT); @@ -83,13 +81,13 @@ void BESCSpindle :: init() { } // prints the startup message of the spindle config -void BESCSpindle :: config_message() { +void BESCSpindle ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "BESC spindle on Pin:%s Min:%0.2fms Max:%0.2fms Freq:%dHz Res:%dbits", pinName(_output_pin).c_str(), - BESC_MIN_PULSE_SECS * 1000.0, // convert to milliseconds - BESC_MAX_PULSE_SECS * 1000.0, // convert to milliseconds + BESC_MIN_PULSE_SECS * 1000.0, // convert to milliseconds + BESC_MAX_PULSE_SECS * 1000.0, // convert to milliseconds _pwm_freq, _pwm_precision); } @@ -101,7 +99,7 @@ uint32_t BESCSpindle::set_rpm(uint32_t rpm) { return rpm; // apply speed overrides - rpm = rpm * sys.spindle_speed_ovr / 100; // Scale by spindle speed override value (percent) + rpm = rpm * sys.spindle_speed_ovr / 100; // Scale by spindle speed override value (percent) // apply limits limits if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) @@ -111,7 +109,7 @@ uint32_t BESCSpindle::set_rpm(uint32_t rpm) { sys.spindle_speed = rpm; // determine the pwm value - if (rpm == 0) { + if (rpm == 0) { pwm_value = _pwm_off_value; } else { pwm_value = map_uint32_t(rpm, _min_rpm, _max_rpm, _pwm_min_value, _pwm_max_value); diff --git a/Grbl_Esp32/Spindles/DacSpindle.cpp b/Grbl_Esp32/Spindles/DacSpindle.cpp index 1e54d638..c05590e4 100644 --- a/Grbl_Esp32/Spindles/DacSpindle.cpp +++ b/Grbl_Esp32/Spindles/DacSpindle.cpp @@ -24,19 +24,19 @@ #include "SpindleClass.h" // ======================================== DacSpindle ====================================== -void DacSpindle :: init() { +void DacSpindle ::init() { get_pins_and_settings(); if (_output_pin == UNDEFINED_PIN) return; - _min_rpm = rpm_min->get(); - _max_rpm = rpm_max->get(); - _pwm_min_value = 0; // not actually PWM...DAC counts - _pwm_max_value = 255; // not actually PWM...DAC counts - _gpio_ok = true; + _min_rpm = rpm_min->get(); + _max_rpm = rpm_max->get(); + _pwm_min_value = 0; // not actually PWM...DAC counts + _pwm_max_value = 255; // not actually PWM...DAC counts + _gpio_ok = true; - if (_output_pin != GPIO_NUM_25 && _output_pin != GPIO_NUM_26) { // DAC can only be used on these pins + if (_output_pin != GPIO_NUM_25 && _output_pin != GPIO_NUM_26) { // DAC can only be used on these pins _gpio_ok = false; grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle pin invalid GPIO_NUM_%d (pin 25 or 26 only)", _output_pin); return; @@ -46,12 +46,12 @@ void DacSpindle :: init() { pinMode(_direction_pin, OUTPUT); is_reversable = (_direction_pin != UNDEFINED_PIN); - use_delays = true; + use_delays = true; config_message(); } -void DacSpindle :: config_message() { +void DacSpindle ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "DAC spindle Output:%s, Enbl:%s, Dir:%s, Res:8bits", @@ -67,38 +67,38 @@ uint32_t DacSpindle::set_rpm(uint32_t rpm) { uint32_t pwm_value; // apply overrides and limits - rpm = rpm * sys.spindle_speed_ovr / 100; // Scale by spindle speed override value (percent) + rpm = rpm * sys.spindle_speed_ovr / 100; // Scale by spindle speed override value (percent) // Calculate PWM register value based on rpm max/min settings and programmed rpm. if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) { // No PWM range possible. Set simple on/off spindle control pin state. sys.spindle_speed = _max_rpm; - pwm_value = _pwm_max_value; + pwm_value = _pwm_max_value; } else if (rpm <= _min_rpm) { - if (rpm == 0) { // S0 disables spindle + if (rpm == 0) { // S0 disables spindle sys.spindle_speed = 0; - pwm_value = 0; - } else { // Set minimum PWM output - rpm = _min_rpm; + pwm_value = 0; + } else { // Set minimum PWM output + rpm = _min_rpm; sys.spindle_speed = rpm; - pwm_value = 0; + pwm_value = 0; grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Spindle RPM less than min RPM:%5.2f %d", rpm, pwm_value); } } else { // Compute intermediate PWM value with linear spindle speed model. // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. sys.spindle_speed = rpm; - + pwm_value = map_uint32_t(rpm, _min_rpm, _max_rpm, _pwm_min_value, _pwm_max_value); } - + set_output(pwm_value); return rpm; } -void DacSpindle :: set_output(uint32_t duty) { +void DacSpindle ::set_output(uint32_t duty) { if (_gpio_ok) { - dacWrite(_output_pin, (uint8_t)duty); + dacWrite(_output_pin, (uint8_t)duty); } } diff --git a/Grbl_Esp32/Spindles/HuanyangSpindle.cpp b/Grbl_Esp32/Spindles/HuanyangSpindle.cpp index fdd9e81f..1b1d1a64 100644 --- a/Grbl_Esp32/Spindles/HuanyangSpindle.cpp +++ b/Grbl_Esp32/Spindles/HuanyangSpindle.cpp @@ -113,41 +113,41 @@ #include "driver/uart.h" -#define HUANYANG_UART_PORT UART_NUM_2 // hard coded for this port right now -#define ECHO_TEST_CTS UART_PIN_NO_CHANGE // CTS pin is not used -#define HUANYANG_BUF_SIZE 127 -#define HUANYANG_QUEUE_SIZE 10 // numv\ber of commands that can be queued up. -#define RESPONSE_WAIT_TICKS 50 // how long to wait for a response -#define HUANYANG_MAX_MSG_SIZE 16 // more than enough for a modbus message -#define HUANYANG_POLL_RATE 200 // in milliseconds betwwen commands +#define HUANYANG_UART_PORT UART_NUM_2 // hard coded for this port right now +#define ECHO_TEST_CTS UART_PIN_NO_CHANGE // CTS pin is not used +#define HUANYANG_BUF_SIZE 127 +#define HUANYANG_QUEUE_SIZE 10 // numv\ber of commands that can be queued up. +#define RESPONSE_WAIT_TICKS 50 // how long to wait for a response +#define HUANYANG_MAX_MSG_SIZE 16 // more than enough for a modbus message +#define HUANYANG_POLL_RATE 200 // in milliseconds betwwen commands // OK to change these // #define them in your machine definition file if you want different values #ifndef HUANYANG_ADDR - #define HUANYANG_ADDR 0x01 +# define HUANYANG_ADDR 0x01 #endif #ifndef HUANYANG_BAUD_RATE - #define HUANYANG_BAUD_RATE 9600 // PD164 setting +# define HUANYANG_BAUD_RATE 9600 // PD164 setting #endif // communication task and queue stuff typedef struct { uint8_t tx_length; uint8_t rx_length; - bool critical; - char msg[HUANYANG_MAX_MSG_SIZE]; + bool critical; + char msg[HUANYANG_MAX_MSG_SIZE]; } hy_command_t; typedef enum : uint8_t { - READ_SET_FREQ = 0, // The set frequency - READ_OUTPUT_FREQ = 1, // The current operating frequency - READ_OUTPUT_AMPS = 2, // - READ_SET_RPM = 3, // This is the last requested freq even in off mode - READ_DC_VOLTAGE = 4, // - READ_AC_VOLTAGE = 5, // - READ_CONT = 6, // counting value??? - READ_TEMP = 7, // + READ_SET_FREQ = 0, // The set frequency + READ_OUTPUT_FREQ = 1, // The current operating frequency + READ_OUTPUT_AMPS = 2, // + READ_SET_RPM = 3, // This is the last requested freq even in off mode + READ_DC_VOLTAGE = 4, // + READ_AC_VOLTAGE = 5, // + READ_CONT = 6, // counting value??? + READ_TEMP = 7, // } read_register_t; QueueHandle_t hy_cmd_queue; @@ -158,14 +158,13 @@ bool hy_spindle_ok = true; // The communications task void vfd_cmd_task(void* pvParameters) { - static bool unresponsive = false; // to pop off a message once each time it becomes unresponsive - uint8_t reg_item = 0x00; + static bool unresponsive = false; // to pop off a message once each time it becomes unresponsive + uint8_t reg_item = 0x00; hy_command_t next_cmd; - uint8_t rx_message[HUANYANG_MAX_MSG_SIZE]; + uint8_t rx_message[HUANYANG_MAX_MSG_SIZE]; while (true) { if (xQueueReceive(hy_cmd_queue, &next_cmd, 0) == pdTRUE) { - uart_flush(HUANYANG_UART_PORT); //report_hex_msg(next_cmd.msg, "Tx: ", next_cmd.tx_length); uart_write_bytes(HUANYANG_UART_PORT, next_cmd.msg, next_cmd.tx_length); @@ -183,29 +182,27 @@ void vfd_cmd_task(void* pvParameters) { } } else { // success - unresponsive = false; + unresponsive = false; //report_hex_msg(rx_message, "Rx: ", read_length); - uint32_t ret_value = ((uint32_t)rx_message[4] << 8) + rx_message[5]; - //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Item:%d value:%05d ", rx_message[3], ret_value); + uint32_t ret_value = ((uint32_t)rx_message[4] << 8) + rx_message[5]; + //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Item:%d value:%05d ", rx_message[3], ret_value); } } else { - HuanyangSpindle :: read_value(reg_item); // only this appears to work all the time. Other registers are flakey. + HuanyangSpindle ::read_value(reg_item); // only this appears to work all the time. Other registers are flakey. if (reg_item < 0x03) reg_item++; - else - { - reg_item = 0x00; + else { + reg_item = 0x00; } - } - vTaskDelay(HUANYANG_POLL_RATE); // TODO: What is the best value here? + vTaskDelay(HUANYANG_POLL_RATE); // TODO: What is the best value here? } } // ================== Class methods ================================== -void HuanyangSpindle :: init() { +void HuanyangSpindle ::init() { hy_spindle_ok = true; // initialize // fail if required items are not defined @@ -214,55 +211,46 @@ void HuanyangSpindle :: init() { return; } - if (! _task_running) { // init can happen many times, we only want to start one task + if (!_task_running) { // init can happen many times, we only want to start one task hy_cmd_queue = xQueueCreate(HUANYANG_QUEUE_SIZE, sizeof(hy_command_t)); - xTaskCreatePinnedToCore(vfd_cmd_task, // task - "vfd_cmdTaskHandle", // name for task - 2048, // size of task stack - NULL, // parameters - 1, // priority + xTaskCreatePinnedToCore(vfd_cmd_task, // task + "vfd_cmdTaskHandle", // name for task + 2048, // size of task stack + NULL, // parameters + 1, // priority &vfd_cmdTaskHandle, - 0 // core - ); + 0 // core + ); _task_running = true; - } + } // this allows us to init() again later. // If you change certain settings, init() gets called agian uart_driver_delete(HUANYANG_UART_PORT); uart_config_t uart_config = { - .baud_rate = HUANYANG_BAUD_RATE, - .data_bits = UART_DATA_8_BITS, - .parity = UART_PARITY_DISABLE, - .stop_bits = UART_STOP_BITS_1, - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .baud_rate = HUANYANG_BAUD_RATE, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .rx_flow_ctrl_thresh = 122, }; uart_param_config(HUANYANG_UART_PORT, &uart_config); - uart_set_pin(HUANYANG_UART_PORT, - _txd_pin, - _rxd_pin, - _rts_pin, - UART_PIN_NO_CHANGE); + uart_set_pin(HUANYANG_UART_PORT, _txd_pin, _rxd_pin, _rts_pin, UART_PIN_NO_CHANGE); - uart_driver_install(HUANYANG_UART_PORT, - HUANYANG_BUF_SIZE * 2, - 0, - 0, - NULL, - 0); + uart_driver_install(HUANYANG_UART_PORT, HUANYANG_BUF_SIZE * 2, 0, 0, NULL, 0); uart_set_mode(HUANYANG_UART_PORT, UART_MODE_RS485_HALF_DUPLEX); - is_reversable = true; // these VFDs are always reversable - use_delays = true; + is_reversable = true; // these VFDs are always reversable + use_delays = true; // _current_rpm = 0; - _state = SPINDLE_DISABLE; + _state = SPINDLE_DISABLE; config_message(); } @@ -270,9 +258,7 @@ void HuanyangSpindle :: init() { // Checks for all the required pin definitions // It returns a message for each missing pin // Returns true if all pins are defined. -bool HuanyangSpindle :: get_pins_and_settings() { - - +bool HuanyangSpindle ::get_pins_and_settings() { #ifdef HUANYANG_TXD_PIN _txd_pin = HUANYANG_TXD_PIN; #else @@ -296,16 +282,16 @@ bool HuanyangSpindle :: get_pins_and_settings() { if (laser_mode->get()) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Huanyang spindle disabled in laser mode. Set $GCode/LaserMode=Off and restart"); - hy_spindle_ok = false; + hy_spindle_ok = false; } _min_rpm = rpm_min->get(); - _max_rpm = rpm_max->get(); + _max_rpm = rpm_max->get(); return hy_spindle_ok; } -void HuanyangSpindle :: config_message() { +void HuanyangSpindle ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Huanyang Spindle Tx:%s Rx:%s RTS:%s", @@ -314,15 +300,14 @@ void HuanyangSpindle :: config_message() { pinName(_rts_pin).c_str()); } - -void HuanyangSpindle :: set_state(uint8_t state, uint32_t rpm) { +void HuanyangSpindle ::set_state(uint8_t state, uint32_t rpm) { if (sys.abort) - return; // Block during abort. + return; // Block during abort. bool critical = (sys.state == STATE_CYCLE || state != SPINDLE_DISABLE); - if (_current_state != state) { // already at the desired state. This function gets called a lot. - set_mode(state, critical); // critical if we are in a job + if (_current_state != state) { // already at the desired state. This function gets called a lot. + set_mode(state, critical); // critical if we are in a job set_rpm(rpm); if (state == SPINDLE_DISABLE) { sys.spindle_speed = 0; @@ -337,16 +322,16 @@ void HuanyangSpindle :: set_state(uint8_t state, uint32_t rpm) { set_rpm(rpm); } - _current_state = state; // store locally for faster get_state() + _current_state = state; // store locally for faster get_state() - sys.report_ovr_counter = 0; // Set to report change immediately + sys.report_ovr_counter = 0; // Set to report change immediately return; } -bool HuanyangSpindle :: set_mode(uint8_t mode, bool critical) { - - if (!hy_spindle_ok) return false; +bool HuanyangSpindle ::set_mode(uint8_t mode, bool critical) { + if (!hy_spindle_ok) + return false; hy_command_t mode_cmd; @@ -357,14 +342,14 @@ bool HuanyangSpindle :: set_mode(uint8_t mode, bool critical) { mode_cmd.msg[1] = 0x03; mode_cmd.msg[2] = 0x01; - if (mode == SPINDLE_ENABLE_CW) + if (mode == SPINDLE_ENABLE_CW) mode_cmd.msg[3] = 0x01; else if (mode == SPINDLE_ENABLE_CCW) mode_cmd.msg[3] = 0x11; - else { //SPINDLE_DISABLE - mode_cmd.msg[3] = 0x08; - - if (! xQueueReset(hy_cmd_queue)) { + else { //SPINDLE_DISABLE + mode_cmd.msg[3] = 0x08; + + if (!xQueueReset(hy_cmd_queue)) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "VFD spindle off, queue could not be reset"); } } @@ -379,14 +364,14 @@ bool HuanyangSpindle :: set_mode(uint8_t mode, bool critical) { return true; } - -uint32_t HuanyangSpindle :: set_rpm(uint32_t rpm) { - if (!hy_spindle_ok) return 0; +uint32_t HuanyangSpindle ::set_rpm(uint32_t rpm) { + if (!hy_spindle_ok) + return 0; hy_command_t rpm_cmd; // apply override - rpm = rpm * sys.spindle_speed_ovr / 100; // Scale by spindle speed override value (uint8_t percent) + rpm = rpm * sys.spindle_speed_ovr / 100; // Scale by spindle speed override value (uint8_t percent) // apply limits if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) @@ -396,8 +381,8 @@ uint32_t HuanyangSpindle :: set_rpm(uint32_t rpm) { sys.spindle_speed = rpm; - if (rpm == _current_rpm) // prevent setting same RPM twice - return rpm; + if (rpm == _current_rpm) // prevent setting same RPM twice + return rpm; _current_rpm = rpm; @@ -410,7 +395,7 @@ uint32_t HuanyangSpindle :: set_rpm(uint32_t rpm) { rpm_cmd.msg[1] = 0x05; rpm_cmd.msg[2] = 0x02; - uint16_t data = (uint16_t)(rpm * 100 / 60); // send Hz * 10 (Ex:1500 RPM = 25Hz .... Send 2500) + uint16_t data = (uint16_t)(rpm * 100 / 60); // send Hz * 10 (Ex:1500 RPM = 25Hz .... Send 2500) rpm_cmd.msg[3] = (data & 0xFF00) >> 8; rpm_cmd.msg[4] = (data & 0xFF); @@ -425,12 +410,11 @@ uint32_t HuanyangSpindle :: set_rpm(uint32_t rpm) { return rpm; } - // This appears to read the control register and will return an RPM running or not. -void HuanyangSpindle :: read_value(uint8_t reg) { - uint16_t ret_value = 0; +void HuanyangSpindle ::read_value(uint8_t reg) { + uint16_t ret_value = 0; hy_command_t read_cmd; - uint8_t rx_message[HUANYANG_MAX_MSG_SIZE]; + uint8_t rx_message[HUANYANG_MAX_MSG_SIZE]; read_cmd.tx_length = 8; read_cmd.rx_length = 8; @@ -444,7 +428,7 @@ void HuanyangSpindle :: read_value(uint8_t reg) { read_cmd.msg[4] = 0x00; read_cmd.msg[5] = 0x00; - read_cmd.critical = (sys.state == STATE_CYCLE); // only critical if running a job TBD.... maybe spindle on? + read_cmd.critical = (sys.state == STATE_CYCLE); // only critical if running a job TBD.... maybe spindle on? add_ModRTU_CRC(read_cmd.msg, read_cmd.tx_length); @@ -452,12 +436,12 @@ void HuanyangSpindle :: read_value(uint8_t reg) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "VFD Queue Full"); } -void HuanyangSpindle ::stop() { +void HuanyangSpindle ::stop() { set_mode(SPINDLE_DISABLE, false); } // state is cached rather than read right now to prevent delays -uint8_t HuanyangSpindle :: get_state() { +uint8_t HuanyangSpindle ::get_state() { return _state; } @@ -465,16 +449,16 @@ uint8_t HuanyangSpindle :: get_state() { // It then added the CRC to those last 2 bytes // full_msg_len This is the length of the message including the 2 crc bytes // Source: https://ctlsys.com/support/how_to_compute_the_modbus_rtu_message_crc/ -void HuanyangSpindle :: add_ModRTU_CRC(char* buf, int full_msg_len) { +void HuanyangSpindle ::add_ModRTU_CRC(char* buf, int full_msg_len) { uint16_t crc = 0xFFFF; for (int pos = 0; pos < full_msg_len - 2; pos++) { - crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc - for (int i = 8; i != 0; i--) { // Loop over each bit - if ((crc & 0x0001) != 0) { // If the LSB is set - crc >>= 1; // Shift right and XOR 0xA001 + crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc + for (int i = 8; i != 0; i--) { // Loop over each bit + if ((crc & 0x0001) != 0) { // If the LSB is set + crc >>= 1; // Shift right and XOR 0xA001 crc ^= 0xA001; - } else // Else LSB is not set - crc >>= 1; // Just shift right + } else // Else LSB is not set + crc >>= 1; // Just shift right } } // add the calculated Crc to the message diff --git a/Grbl_Esp32/Spindles/Laser.cpp b/Grbl_Esp32/Spindles/Laser.cpp index 53d82712..d42bb7db 100644 --- a/Grbl_Esp32/Spindles/Laser.cpp +++ b/Grbl_Esp32/Spindles/Laser.cpp @@ -23,12 +23,11 @@ // ===================================== Laser ============================================== - -bool Laser :: isRateAdjusted() { - return true; // can use M4 (CCW) laser mode. +bool Laser ::isRateAdjusted() { + return true; // can use M4 (CCW) laser mode. } -void Laser :: config_message() { +void Laser ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Laser spindle on Pin:%s, Freq:%.2fHz, Res:%dbits Laser mode:$32=%d", @@ -37,5 +36,5 @@ void Laser :: config_message() { _pwm_precision, isRateAdjusted()); // the current mode - use_delays = false; // this will override the value set in PWMSpindle intit() + use_delays = false; // this will override the value set in PWMSpindle intit() } diff --git a/Grbl_Esp32/Spindles/NullSpindle.cpp b/Grbl_Esp32/Spindles/NullSpindle.cpp index d3be3ea7..51fe94b9 100644 --- a/Grbl_Esp32/Spindles/NullSpindle.cpp +++ b/Grbl_Esp32/Spindles/NullSpindle.cpp @@ -24,19 +24,19 @@ // ======================= NullSpindle ============================== // NullSpindle is just bunch of do nothing (ignore) methods to be used when you don't want a spindle -void NullSpindle :: init() { +void NullSpindle ::init() { is_reversable = false; - use_delays = false; + use_delays = false; config_message(); } -uint32_t NullSpindle :: set_rpm(uint32_t rpm) { +uint32_t NullSpindle ::set_rpm(uint32_t rpm) { return rpm; } -void NullSpindle :: set_state(uint8_t state, uint32_t rpm) {} -uint8_t NullSpindle :: get_state() { +void NullSpindle ::set_state(uint8_t state, uint32_t rpm) {} +uint8_t NullSpindle ::get_state() { return (SPINDLE_STATE_DISABLE); } -void NullSpindle :: stop() {} -void NullSpindle :: config_message() { +void NullSpindle ::stop() {} +void NullSpindle ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "No spindle"); } diff --git a/Grbl_Esp32/Spindles/PWMSpindle.cpp b/Grbl_Esp32/Spindles/PWMSpindle.cpp index 3f28273d..21dcb742 100644 --- a/Grbl_Esp32/Spindles/PWMSpindle.cpp +++ b/Grbl_Esp32/Spindles/PWMSpindle.cpp @@ -29,13 +29,12 @@ //#include "grbl.h" -void PWMSpindle :: init() { - +void PWMSpindle ::init() { get_pins_and_settings(); if (_output_pin == UNDEFINED_PIN) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle output pin not defined"); - return; // We cannot continue without the output pin + return; // We cannot continue without the output pin } if (_output_pin >= I2S_OUT_PIN_BASE) { @@ -43,55 +42,54 @@ void PWMSpindle :: init() { return; } - ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, _pwm_precision); // setup the channel - ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin + ledcSetup(_spindle_pwm_chan_num, (double)_pwm_freq, _pwm_precision); // setup the channel + ledcAttachPin(_output_pin, _spindle_pwm_chan_num); // attach the PWM to the pin pinMode(_enable_pin, OUTPUT); pinMode(_direction_pin, OUTPUT); - + use_delays = true; - + config_message(); } // Get the GPIO from the machine definition -void PWMSpindle :: get_pins_and_settings() { +void PWMSpindle ::get_pins_and_settings() { // setup all the pins #ifdef SPINDLE_OUTPUT_PIN _output_pin = SPINDLE_OUTPUT_PIN; #else - _output_pin = UNDEFINED_PIN; + _output_pin = UNDEFINED_PIN; #endif #ifdef INVERT_SPINDLE_OUTPUT_PIN _invert_pwm = true; #else - _invert_pwm = false; + _invert_pwm = false; #endif #ifdef SPINDLE_ENABLE_PIN _enable_pin = SPINDLE_ENABLE_PIN; -#ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED +# ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED _off_with_zero_speed = true; -#endif +# endif #else - _enable_pin = UNDEFINED_PIN; + _enable_pin = UNDEFINED_PIN; _off_with_zero_speed = false; #endif - #ifdef SPINDLE_DIR_PIN _direction_pin = SPINDLE_DIR_PIN; #else - _direction_pin = UNDEFINED_PIN; + _direction_pin = UNDEFINED_PIN; #endif is_reversable = (_direction_pin != UNDEFINED_PIN); - _pwm_freq = spindle_pwm_freq->get(); - _pwm_precision = calc_pwm_precision(_pwm_freq); // detewrmine the best precision - _pwm_period = (1 << _pwm_precision); + _pwm_freq = spindle_pwm_freq->get(); + _pwm_precision = calc_pwm_precision(_pwm_freq); // detewrmine the best precision + _pwm_period = (1 << _pwm_precision); if (spindle_pwm_min_value->get() > spindle_pwm_min_value->get()) grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Warning: Spindle min pwm is greater than max. Check $35 and $36"); @@ -102,20 +100,18 @@ void PWMSpindle :: get_pins_and_settings() { _pwm_max_value = (_pwm_period * spindle_pwm_max_value->get() / 100.0); #ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE - _min_rpm = RPM_MIN; - _max_rpm = RPM_MAX; + _min_rpm = RPM_MIN; + _max_rpm = RPM_MAX; _piecewide_linear = true; #else - _min_rpm = rpm_min->get(); - _max_rpm = rpm_max->get(); - _piecewide_linear = false; + _min_rpm = rpm_min->get(); + _max_rpm = rpm_max->get(); + _piecewide_linear = false; #endif // The pwm_gradient is the pwm duty cycle units per rpm // _pwm_gradient = (_pwm_max_value - _pwm_min_value) / (_max_rpm - _min_rpm); - _spindle_pwm_chan_num = 0; // Channel 0 is reserved for spindle use - - + _spindle_pwm_chan_num = 0; // Channel 0 is reserved for spindle use } uint32_t PWMSpindle::set_rpm(uint32_t rpm) { @@ -127,7 +123,7 @@ uint32_t PWMSpindle::set_rpm(uint32_t rpm) { //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "set_rpm(%d)", rpm); // apply override - rpm = rpm * sys.spindle_speed_ovr / 100; // Scale by spindle speed override value (uint8_t percent) + rpm = rpm * sys.spindle_speed_ovr / 100; // Scale by spindle speed override value (uint8_t percent) // apply limits if ((_min_rpm >= _max_rpm) || (rpm >= _max_rpm)) @@ -156,9 +152,9 @@ uint32_t PWMSpindle::set_rpm(uint32_t rpm) { void PWMSpindle::set_state(uint8_t state, uint32_t rpm) { if (sys.abort) - return; // Block during abort. + return; // Block during abort. - if (state == SPINDLE_DISABLE) { // Halt or set spindle direction and rpm. + if (state == SPINDLE_DISABLE) { // Halt or set spindle direction and rpm. sys.spindle_speed = 0; stop(); if (use_delays && (_current_state != state)) { @@ -169,7 +165,7 @@ void PWMSpindle::set_state(uint8_t state, uint32_t rpm) { } else { set_spindle_dir_pin(state == SPINDLE_ENABLE_CW); set_rpm(rpm); - set_enable_pin(state != SPINDLE_DISABLE); // must be done after setting rpm for enable features to work + set_enable_pin(state != SPINDLE_DISABLE); // must be done after setting rpm for enable features to work if (use_delays && (_current_state != state)) { //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "SpinUp Start %d", rpm); mc_dwell(spindle_delay_spinup->get()); @@ -179,11 +175,11 @@ void PWMSpindle::set_state(uint8_t state, uint32_t rpm) { _current_state = state; - sys.report_ovr_counter = 0; // Set to report change immediately + sys.report_ovr_counter = 0; // Set to report change immediately } uint8_t PWMSpindle::get_state() { - if (_current_pwm_duty == 0 || _output_pin == UNDEFINED_PIN) + if (_current_pwm_duty == 0 || _output_pin == UNDEFINED_PIN) return (SPINDLE_STATE_DISABLE); if (_direction_pin != UNDEFINED_PIN) return digitalRead(_direction_pin) ? SPINDLE_STATE_CW : SPINDLE_STATE_CCW; @@ -194,11 +190,10 @@ void PWMSpindle::stop() { // inverts are delt with in methods set_enable_pin(false); set_output(_pwm_off_value); - } // prints the startup message of the spindle config -void PWMSpindle :: config_message() { +void PWMSpindle ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "PWM spindle Output:%s, Enbl:%s, Dir:%s, Freq:%dHz, Res:%dbits", @@ -209,10 +204,7 @@ void PWMSpindle :: config_message() { _pwm_precision); } - void PWMSpindle::set_output(uint32_t duty) { - - if (_output_pin == UNDEFINED_PIN) return; @@ -222,7 +214,7 @@ void PWMSpindle::set_output(uint32_t duty) { _current_pwm_duty = duty; - if (_invert_pwm) + if (_invert_pwm) duty = (1 << _pwm_precision) - duty; //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "set_output(%d)", duty); @@ -231,11 +223,10 @@ void PWMSpindle::set_output(uint32_t duty) { } void PWMSpindle::set_enable_pin(bool enable) { - if (_enable_pin == UNDEFINED_PIN) return; - if (_off_with_zero_speed && sys.spindle_speed == 0) + if (_off_with_zero_speed && sys.spindle_speed == 0) enable = false; #ifndef INVERT_SPINDLE_ENABLE_PIN @@ -250,14 +241,13 @@ void PWMSpindle::set_spindle_dir_pin(bool Clockwise) { digitalWrite(_direction_pin, Clockwise); } - /* Calculate the highest precision of a PWM based on the frequency in bits 80,000,000 / freq = period determine the highest precision where (1 << precision) < period */ -uint8_t PWMSpindle :: calc_pwm_precision(uint32_t freq) { +uint8_t PWMSpindle ::calc_pwm_precision(uint32_t freq) { uint8_t precision = 0; // increase the precision (bits) until it exceeds allow by frequency the max or is 16 diff --git a/Grbl_Esp32/Spindles/RelaySpindle.cpp b/Grbl_Esp32/Spindles/RelaySpindle.cpp index f90b9b90..bf287303 100644 --- a/Grbl_Esp32/Spindles/RelaySpindle.cpp +++ b/Grbl_Esp32/Spindles/RelaySpindle.cpp @@ -36,13 +36,13 @@ void RelaySpindle::init() { pinMode(_direction_pin, OUTPUT); is_reversable = (_direction_pin != UNDEFINED_PIN); - use_delays = true; + use_delays = true; config_message(); } // prints the startup message of the spindle config -void RelaySpindle :: config_message() { +void RelaySpindle ::config_message() { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Relay spindle Output:%s, Enbl:%s, Dir:%s", @@ -56,15 +56,14 @@ uint32_t RelaySpindle::set_rpm(uint32_t rpm) { return rpm; sys.spindle_speed = rpm; - set_output(rpm != 0); - + set_output(rpm != 0); return rpm; } void RelaySpindle::set_output(uint32_t duty) { #ifdef INVERT_SPINDLE_PWM - duty = (duty == 0); // flip duty + duty = (duty == 0); // flip duty #endif - digitalWrite(_output_pin, duty > 0); // anything greater + digitalWrite(_output_pin, duty > 0); // anything greater } diff --git a/Grbl_Esp32/Spindles/SpindleClass.cpp b/Grbl_Esp32/Spindles/SpindleClass.cpp index 75c3b2ce..af3da724 100644 --- a/Grbl_Esp32/Spindles/SpindleClass.cpp +++ b/Grbl_Esp32/Spindles/SpindleClass.cpp @@ -36,61 +36,42 @@ #include "BESCSpindle.cpp" #include "10vSpindle.cpp" - // An instance of each type of spindle is created here. // This allows the spindle to be dynamicly switched -NullSpindle null_spindle; -PWMSpindle pwm_spindle; -RelaySpindle relay_spindle; -Laser laser; -DacSpindle dac_spindle; +NullSpindle null_spindle; +PWMSpindle pwm_spindle; +RelaySpindle relay_spindle; +Laser laser; +DacSpindle dac_spindle; HuanyangSpindle huanyang_spindle; -BESCSpindle besc_spindle; -_10vSpindle _10v_spindle; - +BESCSpindle besc_spindle; +_10vSpindle _10v_spindle; void spindle_select() { - switch (spindle_type->get()) { - case SPINDLE_TYPE_PWM: - spindle = &pwm_spindle; - break; - case SPINDLE_TYPE_RELAY: - spindle = &relay_spindle; - break; - case SPINDLE_TYPE_LASER: - spindle = &laser; - break; - case SPINDLE_TYPE_DAC: - spindle = &dac_spindle; - break; - case SPINDLE_TYPE_HUANYANG: - spindle = &huanyang_spindle; - break; - case SPINDLE_TYPE_BESC: - spindle = &besc_spindle; - break; - case SPINDLE_TYPE_10V: - spindle = &_10v_spindle; - break; - case SPINDLE_TYPE_NONE: - default: - spindle = &null_spindle; - break; + case SPINDLE_TYPE_PWM: spindle = &pwm_spindle; break; + case SPINDLE_TYPE_RELAY: spindle = &relay_spindle; break; + case SPINDLE_TYPE_LASER: spindle = &laser; break; + case SPINDLE_TYPE_DAC: spindle = &dac_spindle; break; + case SPINDLE_TYPE_HUANYANG: spindle = &huanyang_spindle; break; + case SPINDLE_TYPE_BESC: spindle = &besc_spindle; break; + case SPINDLE_TYPE_10V: spindle = &_10v_spindle; break; + case SPINDLE_TYPE_NONE: + default: spindle = &null_spindle; break; } - + spindle->init(); } // ========================= Spindle ================================== bool Spindle::isRateAdjusted() { - return false; // default for basic spindle is false + return false; // default for basic spindle is false } -void Spindle :: spindle_sync(uint8_t state, uint32_t rpm) { +void Spindle ::spindle_sync(uint8_t state, uint32_t rpm) { if (sys.state == STATE_CHECK_MODE) return; - protocol_buffer_synchronize(); // Empty planner buffer to ensure spindle is set when programmed. + protocol_buffer_synchronize(); // Empty planner buffer to ensure spindle is set when programmed. set_state(state, rpm); } diff --git a/Grbl_Esp32/Spindles/SpindleClass.h b/Grbl_Esp32/Spindles/SpindleClass.h index 77b84de4..5560c26f 100644 --- a/Grbl_Esp32/Spindles/SpindleClass.h +++ b/Grbl_Esp32/Spindles/SpindleClass.h @@ -26,199 +26,190 @@ */ -#define SPINDLE_STATE_DISABLE 0 // Must be zero. -#define SPINDLE_STATE_CW bit(0) -#define SPINDLE_STATE_CCW bit(1) +#define SPINDLE_STATE_DISABLE 0 // Must be zero. +#define SPINDLE_STATE_CW bit(0) +#define SPINDLE_STATE_CCW bit(1) - -#define SPINDLE_TYPE_NONE 0 -#define SPINDLE_TYPE_PWM 1 -#define SPINDLE_TYPE_RELAY 2 -#define SPINDLE_TYPE_LASER 3 -#define SPINDLE_TYPE_DAC 4 -#define SPINDLE_TYPE_HUANYANG 5 -#define SPINDLE_TYPE_BESC 6 -#define SPINDLE_TYPE_10V 7 +#define SPINDLE_TYPE_NONE 0 +#define SPINDLE_TYPE_PWM 1 +#define SPINDLE_TYPE_RELAY 2 +#define SPINDLE_TYPE_LASER 3 +#define SPINDLE_TYPE_DAC 4 +#define SPINDLE_TYPE_HUANYANG 5 +#define SPINDLE_TYPE_BESC 6 +#define SPINDLE_TYPE_10V 7 #include "../grbl.h" #include #include "driver/uart.h" - // =============== No floats! =========================== // ================ NO FLOATS! ========================== // This is the base class. Do not use this as your spindle class Spindle { - public: - virtual void init(); // not in constructor because this also gets called when $$ settings change +public: + virtual void init(); // not in constructor because this also gets called when $$ settings change virtual uint32_t set_rpm(uint32_t rpm); - virtual void set_state(uint8_t state, uint32_t rpm); - virtual uint8_t get_state(); - virtual void stop(); - virtual void config_message(); - virtual bool isRateAdjusted(); - virtual void spindle_sync(uint8_t state, uint32_t rpm); + virtual void set_state(uint8_t state, uint32_t rpm); + virtual uint8_t get_state(); + virtual void stop(); + virtual void config_message(); + virtual bool isRateAdjusted(); + virtual void spindle_sync(uint8_t state, uint32_t rpm); - bool is_reversable; - bool use_delays; // will SpinUp and SpinDown delays be used. + bool is_reversable; + bool use_delays; // will SpinUp and SpinDown delays be used. uint8_t _current_state; }; // This is a dummy spindle that has no I/O. // It is used to ignore spindle commands when no spinde is desired class NullSpindle : public Spindle { - public: - void init(); +public: + void init(); uint32_t set_rpm(uint32_t rpm); - void set_state(uint8_t state, uint32_t rpm); - uint8_t get_state(); - void stop(); - void config_message(); + void set_state(uint8_t state, uint32_t rpm); + uint8_t get_state(); + void stop(); + void config_message(); }; // This adds support for PWM class PWMSpindle : public Spindle { - public: - void init(); +public: + void init(); virtual uint32_t set_rpm(uint32_t rpm); - void set_state(uint8_t state, uint32_t rpm); - uint8_t get_state(); - void stop(); - void config_message(); + void set_state(uint8_t state, uint32_t rpm); + uint8_t get_state(); + void stop(); + void config_message(); - private: +private: void set_spindle_dir_pin(bool Clockwise); - - - protected: - - int32_t _current_pwm_duty; +protected: + int32_t _current_pwm_duty; uint32_t _min_rpm; uint32_t _max_rpm; uint32_t _pwm_off_value; uint32_t _pwm_min_value; uint32_t _pwm_max_value; - uint8_t _output_pin; - uint8_t _enable_pin; - uint8_t _direction_pin; - uint8_t _spindle_pwm_chan_num; + uint8_t _output_pin; + uint8_t _enable_pin; + uint8_t _direction_pin; + uint8_t _spindle_pwm_chan_num; uint32_t _pwm_freq; - uint32_t _pwm_period; // how many counts in 1 period - uint8_t _pwm_precision; - bool _piecewide_linear; - bool _off_with_zero_speed; - bool _invert_pwm; + uint32_t _pwm_period; // how many counts in 1 period + uint8_t _pwm_precision; + bool _piecewide_linear; + bool _off_with_zero_speed; + bool _invert_pwm; //uint32_t _pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. virtual void set_output(uint32_t duty); - void set_enable_pin(bool enable_pin); - void get_pins_and_settings(); - uint8_t calc_pwm_precision(uint32_t freq); + void set_enable_pin(bool enable_pin); + void get_pins_and_settings(); + uint8_t calc_pwm_precision(uint32_t freq); }; // This is for an on/off spindle all RPMs above 0 are on class RelaySpindle : public PWMSpindle { - public: - void init(); - void config_message(); +public: + void init(); + void config_message(); uint32_t set_rpm(uint32_t rpm); - protected: + +protected: void set_output(uint32_t duty); }; // this is the same as a PWM spindle but the M4 compensation is supported. class Laser : public PWMSpindle { - public: +public: bool isRateAdjusted(); void config_message(); }; // This uses one of the (2) DAC pins on ESP32 to output a voltage class DacSpindle : public PWMSpindle { - public: - void init(); - void config_message(); +public: + void init(); + void config_message(); uint32_t set_rpm(uint32_t rpm); - private: - bool _gpio_ok; // DAC is on a valid pin - protected: - void set_output(uint32_t duty); // sets DAC instead of PWM + +private: + bool _gpio_ok; // DAC is on a valid pin +protected: + void set_output(uint32_t duty); // sets DAC instead of PWM }; class HuanyangSpindle : public Spindle { - private: - uint16_t ModRTU_CRC(char* buf, int len); - +private: + uint16_t ModRTU_CRC(char* buf, int len); + bool set_mode(uint8_t mode, bool critical); - + bool get_pins_and_settings(); uint32_t _current_rpm; - uint8_t _txd_pin; - uint8_t _rxd_pin; - uint8_t _rts_pin; - uint8_t _state; - bool _task_running; + uint8_t _txd_pin; + uint8_t _rxd_pin; + uint8_t _rts_pin; + uint8_t _state; + bool _task_running; - public: - HuanyangSpindle() { - _task_running = false; - } - void init(); - void config_message(); - void set_state(uint8_t state, uint32_t rpm); - uint8_t get_state(); - uint32_t set_rpm(uint32_t rpm); - void stop(); +public: + HuanyangSpindle() { _task_running = false; } + void init(); + void config_message(); + void set_state(uint8_t state, uint32_t rpm); + uint8_t get_state(); + uint32_t set_rpm(uint32_t rpm); + void stop(); static void read_value(uint8_t reg); - static void add_ModRTU_CRC(char* buf, int full_msg_len); + static void add_ModRTU_CRC(char* buf, int full_msg_len); - protected: +protected: uint32_t _min_rpm; uint32_t _max_rpm; - - - }; class BESCSpindle : public PWMSpindle { - public: - void init(); - void config_message(); +public: + void init(); + void config_message(); uint32_t set_rpm(uint32_t rpm); }; class _10vSpindle : public PWMSpindle { - public: - void init(); - void config_message(); +public: + void init(); + void config_message(); uint32_t set_rpm(uint32_t rpm); - uint8_t _forward_pin; - uint8_t _reverse_pin; + uint8_t _forward_pin; + uint8_t _reverse_pin; //void set_state(uint8_t state, uint32_t rpm); uint8_t get_state(); - void stop(); - protected: + void stop(); + +protected: void set_enable_pin(bool enable_pin); void set_spindle_dir_pin(bool Clockwise); - }; extern Spindle* spindle; - -extern NullSpindle null_spindle; -extern PWMSpindle pwm_spindle; -extern RelaySpindle relay_spindle; -extern Laser laser; -extern DacSpindle dac_spindle; +extern NullSpindle null_spindle; +extern PWMSpindle pwm_spindle; +extern RelaySpindle relay_spindle; +extern Laser laser; +extern DacSpindle dac_spindle; extern HuanyangSpindle huanyang_spindle; -extern BESCSpindle besc_spindle; -extern _10vSpindle _10v_spindle; +extern BESCSpindle besc_spindle; +extern _10vSpindle _10v_spindle; void spindle_select(); diff --git a/Grbl_Esp32/WebSettings.cpp b/Grbl_Esp32/WebSettings.cpp index 74e79647..760b5202 100644 --- a/Grbl_Esp32/WebSettings.cpp +++ b/Grbl_Esp32/WebSettings.cpp @@ -48,35 +48,35 @@ IPaddrSetting* wifi_ap_ip; IntSetting* wifi_ap_channel; -StringSetting* wifi_hostname; -EnumSetting* http_enable; -IntSetting* http_port; -EnumSetting* telnet_enable; -IntSetting* telnet_port; -typedef std::map enum_opt_t; -enum_opt_t staModeOptions = { - { "DHCP", DHCP_MODE , }, - { "Static", STATIC_MODE , }, +StringSetting* wifi_hostname; +EnumSetting* http_enable; +IntSetting* http_port; +EnumSetting* telnet_enable; +IntSetting* telnet_port; +typedef std::map enum_opt_t; +enum_opt_t staModeOptions = { + { "DHCP", DHCP_MODE }, + { "Static", STATIC_MODE }, }; #endif #ifdef WIFI_OR_BLUETOOTH EnumSetting* wifi_radio_mode; -enum_opt_t radioOptions = { - { "None", ESP_RADIO_OFF, }, - { "STA", ESP_WIFI_STA, }, - { "AP", ESP_WIFI_AP, }, - { "BT", ESP_BT, }, +enum_opt_t radioOptions = { + { "None", ESP_RADIO_OFF }, + { "STA", ESP_WIFI_STA }, + { "AP", ESP_WIFI_AP }, + { "BT", ESP_BT }, }; enum_opt_t radioEnabledOptions = { - { "NONE", ESP_RADIO_OFF, }, -#ifdef ENABLE_WIFI - { "STA", ESP_WIFI_STA, }, - { "AP", ESP_WIFI_AP, }, -#endif -#ifdef ENABLE_BLUETOOTH - { "BT", ESP_BT, }, -#endif + { "NONE", ESP_RADIO_OFF }, +# ifdef ENABLE_WIFI + { "STA", ESP_WIFI_STA }, + { "AP", ESP_WIFI_AP }, +# endif +# ifdef ENABLE_BLUETOOTH + { "BT", ESP_BT }, +# endif }; #endif @@ -84,24 +84,20 @@ enum_opt_t radioEnabledOptions = { StringSetting* bt_name; #endif - #ifdef ENABLE_NOTIFICATIONS enum_opt_t notificationOptions = { - { "NONE", 0, }, - { "LINE", 3, }, - { "PUSHOVER", 1, }, - { "EMAIL", 2, }, + { "NONE", 0 }, + { "LINE", 3 }, + { "PUSHOVER", 1 }, + { "EMAIL", 2 }, }; -EnumSetting* notification_type; +EnumSetting* notification_type; StringSetting* notification_t1; StringSetting* notification_t2; StringSetting* notification_ts; #endif -enum_opt_t onoffOptions = { - { "OFF", 0, }, - { "ON", 1, } -}; +enum_opt_t onoffOptions = { { "OFF", 0 }, { "ON", 1 } }; static ESPResponseStream* espresponse; @@ -111,26 +107,26 @@ typedef struct { } keyval_t; static keyval_t params[10]; -bool split_params(char *parameter) { +bool split_params(char* parameter) { int i = 0; for (char* s = parameter; *s; s++) { if (*s == '=') { - params[i].value = s+1; - *s = '\0'; + params[i].value = s + 1; + *s = '\0'; // Search backward looking for the start of the key, // either just after a space or at the beginning of the strin if (s == parameter) { return false; } - for (char* k = s-1; k >= parameter; --k) { + for (char* k = s - 1; k >= parameter; --k) { if (*k == '\0') { // If we find a NUL - i.e. the end of the previous key - // before finding a space, the string is malformed. return false; } if (*k == ' ') { - *k = '\0'; - params[i++].key = k+1; + *k = '\0'; + params[i++].key = k + 1; break; } if (k == parameter) { @@ -143,8 +139,8 @@ bool split_params(char *parameter) { return true; } -char nullstr[1] = { '\0' }; -char* get_param(const char *key, bool allowSpaces) { +char nullstr[1] = { '\0' }; +char* get_param(const char* key, bool allowSpaces) { for (keyval_t* p = params; p->key; p++) { if (!strcasecmp(key, p->key)) { if (!allowSpaces) { @@ -173,8 +169,7 @@ err_t WebCommand::action(char* value, auth_t auth_level, ESPResponseStream* out) static int webColumn = 0; // We create a variety of print functions to make the rest // of the code more compact and readable. -static void webPrint(const char *s) -{ +static void webPrint(const char* s) { if (espresponse) { espresponse->print(s); webColumn += strlen(s); @@ -185,64 +180,54 @@ static void webPrintSetColumn(int column) { webPrint(" "); } } -static void webPrint(String s) -{ +static void webPrint(String s) { webPrint(s.c_str()); } -static void webPrint(const char *s1, const char *s2) -{ +static void webPrint(const char* s1, const char* s2) { webPrint(s1); webPrint(s2); } -static void webPrint(const char *s1, String s2) -{ +static void webPrint(const char* s1, String s2) { webPrint(s1); webPrint(s2.c_str()); } -static void webPrint(const char *s1, const char *s2, const char *s3) -{ +static void webPrint(const char* s1, const char* s2, const char* s3) { webPrint(s1); webPrint(s2); webPrint(s3); } -static void webPrintln(const char *s) -{ +static void webPrintln(const char* s) { webPrint(s); webPrint("\r\n"); webColumn = 0; } -static void webPrintln(String s) -{ +static void webPrintln(String s) { webPrintln(s.c_str()); } -static void webPrintln(const char *s1, const char *s2) -{ +static void webPrintln(const char* s1, const char* s2) { webPrint(s1); webPrintln(s2); } -static void webPrintln(const char *s, IPAddress ip) -{ +static void webPrintln(const char* s, IPAddress ip) { webPrint(s); webPrintln(ip.toString().c_str()); } -static void webPrintln(const char *s, String s2) -{ +static void webPrintln(const char* s, String s2) { webPrintln(s, s2.c_str()); } -char *trim(char *str) -{ - char *end; +char* trim(char* str) { + char* end; // Trim leading space - while(isspace((unsigned char)*str)) { + while (isspace((unsigned char)*str)) { str++; } - if(*str == 0) { // All spaces? + if (*str == 0) { // All spaces? return str; } // Trim trailing space end = str + strlen(str) - 1; - while(end > str && isspace((unsigned char)*end)) { + while (end > str && isspace((unsigned char)*end)) { end--; } // Write new null terminator character @@ -250,64 +235,56 @@ char *trim(char *str) return str; } -static void print_mac(const char *s, String mac) -{ +static void print_mac(const char* s, String mac) { webPrint(s); webPrint(" ("); webPrint(mac); webPrintln(")"); } -static err_t showFwInfo(char *parameter, auth_t auth_level) { // ESP800 - webPrint("FW version:" GRBL_VERSION " (" GRBL_VERSION_BUILD ")" " # FW target:grbl-embedded # FW HW:"); - #ifdef ENABLE_SD_CARD - webPrint("Direct SD"); - #else - webPrint("No SD"); - #endif +static err_t showFwInfo(char* parameter, auth_t auth_level) { // ESP800 + webPrint("FW version:" GRBL_VERSION " (" GRBL_VERSION_BUILD ")" + " # FW target:grbl-embedded # FW HW:"); +#ifdef ENABLE_SD_CARD + webPrint("Direct SD"); +#else + webPrint("No SD"); +#endif webPrint(" # primary sd:/sd # secondary sd:none # authentication:"); #ifdef ENABLE_AUTHENTICATION webPrint("yes"); #else webPrint("no"); #endif -#if defined (ENABLE_WIFI) - #if defined (ENABLE_HTTP) - webPrint(" # webcommunication: Sync: ", String(web_server.port() + 1)); - webPrint(":"); - switch (WiFi.getMode()) { - case WIFI_MODE_AP: - webPrint(WiFi.softAPIP().toString()); - break; - case WIFI_MODE_STA: - webPrint(WiFi.localIP().toString()); - break; - case WIFI_MODE_APSTA: - webPrint(WiFi.softAPIP().toString()); - break; - default: - webPrint("0.0.0.0"); - break; - } - #endif - webPrint(" # hostname:", wifi_config.Hostname()); - if (WiFi.getMode() == WIFI_AP) { - webPrint("(AP mode)"); - } +#if defined(ENABLE_WIFI) +# if defined(ENABLE_HTTP) + webPrint(" # webcommunication: Sync: ", String(web_server.port() + 1)); + webPrint(":"); + switch (WiFi.getMode()) { + case WIFI_MODE_AP: webPrint(WiFi.softAPIP().toString()); break; + case WIFI_MODE_STA: webPrint(WiFi.localIP().toString()); break; + case WIFI_MODE_APSTA: webPrint(WiFi.softAPIP().toString()); break; + default: webPrint("0.0.0.0"); break; + } +# endif + webPrint(" # hostname:", wifi_config.Hostname()); + if (WiFi.getMode() == WIFI_AP) { + webPrint("(AP mode)"); + } #endif - //to save time in decoding `?` - webPrintln(" # axis:", String(N_AXIS)); + //to save time in decoding `?` + webPrintln(" # axis:", String(N_AXIS)); return STATUS_OK; } -static err_t SPIFFSSize(char *parameter, auth_t auth_level) { // ESP720 +static err_t SPIFFSSize(char* parameter, auth_t auth_level) { // ESP720 webPrint(parameter); webPrint("SPIFFS Total:", ESPResponseStream::formatBytes(SPIFFS.totalBytes())); webPrintln(" Used:", ESPResponseStream::formatBytes(SPIFFS.usedBytes())); return STATUS_OK; } -static err_t formatSpiffs(char *parameter, auth_t auth_level) { // ESP710 +static err_t formatSpiffs(char* parameter, auth_t auth_level) { // ESP710 if (strcmp(parameter, "FORMAT") != 0) { webPrintln("Parameter must be FORMAT"); return STATUS_INVALID_VALUE; @@ -318,7 +295,7 @@ static err_t formatSpiffs(char *parameter, auth_t auth_level) { // ESP710 return STATUS_OK; } -static err_t runFile(char *parameter, auth_t auth_level) { // ESP700 +static err_t runFile(char* parameter, auth_t auth_level) { // ESP700 String path = trim(parameter); if ((path.length() > 0) && (path[0] != '/')) { path = "/" + path; @@ -328,7 +305,7 @@ static err_t runFile(char *parameter, auth_t auth_level) { // ESP700 return STATUS_SD_FILE_NOT_FOUND; } File currentfile = SPIFFS.open(path, FILE_READ); - if (!currentfile) {//if file open success + if (!currentfile) { //if file open success return STATUS_SD_FAILED_OPEN_FILE; } //until no line in file @@ -341,7 +318,7 @@ static err_t runFile(char *parameter, auth_t auth_level) { // ESP700 currentline.getBytes(line, 255); // TODO Settings - feed into command interpreter // while accumulating error codes - err = execute_line((char *)line, CLIENT_WEBUI, auth_level); + err = execute_line((char*)line, CLIENT_WEBUI, auth_level); if (err != STATUS_OK) { accumErr = err; } @@ -353,7 +330,7 @@ static err_t runFile(char *parameter, auth_t auth_level) { // ESP700 } #ifdef ENABLE_NOTIFICATIONS -static err_t showSetNotification(char *parameter, auth_t auth_level) { // ESP610 +static err_t showSetNotification(char* parameter, auth_t auth_level) { // ESP610 if (*parameter == '\0') { webPrint("", notification_type->getStringValue()); webPrintln(" ", notification_ts->getStringValue()); @@ -362,10 +339,10 @@ static err_t showSetNotification(char *parameter, auth_t auth_level) { // ESP610 if (!split_params(parameter)) { return STATUS_INVALID_VALUE; } - char *ts = get_param("TS", false); - char *t2 = get_param("T2", false); - char *t1 = get_param("T1", false); - char *ty = get_param("type", false); + char* ts = get_param("TS", false); + char* t2 = get_param("T2", false); + char* t1 = get_param("T1", false); + char* ty = get_param("type", false); err_t err = notification_type->setStringValue(ty); if (!err) { err = notification_t1->setStringValue(t1); @@ -377,10 +354,9 @@ static err_t showSetNotification(char *parameter, auth_t auth_level) { // ESP610 err = notification_ts->setStringValue(ts); } return err; - } -static err_t sendMessage(char *parameter, auth_t auth_level) { // ESP600 +static err_t sendMessage(char* parameter, auth_t auth_level) { // ESP600 if (*parameter == '\0') { webPrintln("Invalid message!"); return STATUS_INVALID_VALUE; @@ -394,7 +370,7 @@ static err_t sendMessage(char *parameter, auth_t auth_level) { // ESP600 #endif #ifdef ENABLE_AUTHENTICATION -static err_t setUserPassword(char *parameter, auth_t auth_level) { // ESP555 +static err_t setUserPassword(char* parameter, auth_t auth_level) { // ESP555 if (*parameter == '\0') { user_password->setDefault(); return STATUS_OK; @@ -407,7 +383,7 @@ static err_t setUserPassword(char *parameter, auth_t auth_level) { // ESP555 } #endif -static err_t setSystemMode(char *parameter, auth_t auth_level) { // ESP444 +static err_t setSystemMode(char* parameter, auth_t auth_level) { // ESP444 parameter = trim(parameter); if (strcasecmp(parameter, "RESTART") != 0) { webPrintln("Incorrect command"); @@ -418,7 +394,7 @@ static err_t setSystemMode(char *parameter, auth_t auth_level) { // ESP444 return STATUS_OK; } -static err_t showSysStats(char *parameter, auth_t auth_level) { // ESP420 +static err_t showSysStats(char* parameter, auth_t auth_level) { // ESP420 webPrintln("Chip ID: ", String((uint16_t)(ESP.getEfuseMac() >> 32))); webPrintln("CPU Frequency: ", String(ESP.getCpuFreqMHz()) + "Mhz"); webPrintln("CPU Temperature: ", String(temperatureRead(), 1) + "C"); @@ -427,7 +403,7 @@ static err_t showSysStats(char *parameter, auth_t auth_level) { // ESP420 webPrintln("Flash Size: ", ESPResponseStream::formatBytes(ESP.getFlashChipSize())); // Round baudRate to nearest 100 because ESP32 can say e.g. 115201 - webPrintln("Baud rate: ", String((Serial.baudRate()/100) * 100)); + webPrintln("Baud rate: ", String((Serial.baudRate() / 100) * 100)); webPrintln("Sleep mode: ", WiFi.getSleep() ? "Modem" : "None"); #ifdef ENABLE_WIFI @@ -443,112 +419,105 @@ static err_t showSysStats(char *parameter, auth_t auth_level) { // ESP420 webPrintln("Available Size for update: ", ESPResponseStream::formatBytes(flashsize)); webPrintln("Available Size for SPIFFS: ", ESPResponseStream::formatBytes(SPIFFS.totalBytes())); -#if defined (ENABLE_HTTP) +# if defined(ENABLE_HTTP) webPrintln("Web port: ", String(web_server.port())); -#endif -#if defined (ENABLE_TELNET) +# endif +# if defined(ENABLE_TELNET) webPrintln("Data port: ", String(telnet_server.port())); -#endif +# endif webPrintln("Hostname: ", wifi_config.Hostname()); } webPrint("Current WiFi Mode: "); switch (mode) { - case WIFI_STA: - print_mac("STA", WiFi.macAddress()); + case WIFI_STA: + print_mac("STA", WiFi.macAddress()); - webPrint("Connected to: "); - if (WiFi.isConnected()) { //in theory no need but ... - webPrintln(WiFi.SSID()); - webPrintln("Signal: ", String(wifi_config.getSignal(WiFi.RSSI())) + "%"); + webPrint("Connected to: "); + if (WiFi.isConnected()) { //in theory no need but ... + webPrintln(WiFi.SSID()); + webPrintln("Signal: ", String(wifi_config.getSignal(WiFi.RSSI())) + "%"); - uint8_t PhyMode; - esp_wifi_get_protocol(ESP_IF_WIFI_STA, &PhyMode); - const char *modeName; - switch (PhyMode) { - case WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N: - modeName = "11n"; - break; - case WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G: - modeName = "11g"; - break; - case WIFI_PROTOCOL_11B: - modeName = "11b"; - break; - default: - modeName = "???"; + uint8_t PhyMode; + esp_wifi_get_protocol(ESP_IF_WIFI_STA, &PhyMode); + const char* modeName; + switch (PhyMode) { + case WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N: modeName = "11n"; break; + case WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G: modeName = "11g"; break; + case WIFI_PROTOCOL_11B: modeName = "11b"; break; + default: modeName = "???"; + } + webPrintln("Phy Mode: ", modeName); + + webPrintln("Channel: ", String(WiFi.channel())); + + tcpip_adapter_dhcp_status_t dhcp_status; + tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &dhcp_status); + webPrintln("IP Mode: ", dhcp_status == TCPIP_ADAPTER_DHCP_STARTED ? "DHCP" : "Static"); + webPrintln("IP: ", WiFi.localIP()); + webPrintln("Gateway: ", WiFi.gatewayIP()); + webPrintln("Mask: ", WiFi.subnetMask()); + webPrintln("DNS: ", WiFi.dnsIP()); + + } //this is web command so connection => no command + webPrint("Disabled Mode: "); + print_mac("AP", WiFi.softAPmacAddress()); + break; + case WIFI_AP: + print_mac("AP", WiFi.softAPmacAddress()); + + wifi_config_t conf; + esp_wifi_get_config(ESP_IF_WIFI_AP, &conf); + webPrintln("SSID: ", (const char*)conf.ap.ssid); + webPrintln("Visible: ", (conf.ap.ssid_hidden == 0) ? "Yes" : "No"); + + const char* mode; + switch (conf.ap.authmode) { + case WIFI_AUTH_OPEN: mode = "None"; break; + case WIFI_AUTH_WEP: mode = "WEP"; break; + case WIFI_AUTH_WPA_PSK: mode = "WPA"; break; + case WIFI_AUTH_WPA2_PSK: mode = "WPA2"; break; + default: mode = "WPA/WPA2"; } - webPrintln("Phy Mode: ", modeName); - webPrintln("Channel: ", String(WiFi.channel())); + webPrintln("Authentication: ", mode); + webPrintln("Max Connections: ", String(conf.ap.max_connection)); tcpip_adapter_dhcp_status_t dhcp_status; - tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &dhcp_status); - webPrintln("IP Mode: ", dhcp_status == TCPIP_ADAPTER_DHCP_STARTED ? "DHCP" : "Static"); - webPrintln("IP: ", WiFi.localIP()); - webPrintln("Gateway: ", WiFi.gatewayIP()); - webPrintln("Mask: ", WiFi.subnetMask()); - webPrintln("DNS: ", WiFi.dnsIP()); + tcpip_adapter_dhcps_get_status(TCPIP_ADAPTER_IF_AP, &dhcp_status); + webPrintln("DHCP Server: ", dhcp_status == TCPIP_ADAPTER_DHCP_STARTED ? "Started" : "Stopped"); - } //this is web command so connection => no command - webPrint("Disabled Mode: "); - print_mac("AP", WiFi.softAPmacAddress()); - break; - case WIFI_AP: - print_mac("AP", WiFi.softAPmacAddress()); + webPrintln("IP: ", WiFi.softAPIP()); - wifi_config_t conf; - esp_wifi_get_config(ESP_IF_WIFI_AP, &conf); - webPrintln("SSID: ", (const char*) conf.ap.ssid); - webPrintln("Visible: ", (conf.ap.ssid_hidden == 0) ? "Yes" : "No"); + tcpip_adapter_ip_info_t ip_AP; + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip_AP); + webPrintln("Gateway: ", IPAddress(ip_AP.gw.addr)); + webPrintln("Mask: ", IPAddress(ip_AP.netmask.addr)); - const char *mode; - switch (conf.ap.authmode) { - case WIFI_AUTH_OPEN: mode = "None"; break; - case WIFI_AUTH_WEP: mode = "WEP"; break; - case WIFI_AUTH_WPA_PSK: mode = "WPA"; break; - case WIFI_AUTH_WPA2_PSK: mode = "WPA2"; break; - default: mode = "WPA/WPA2"; - } + wifi_sta_list_t station; + tcpip_adapter_sta_list_t tcpip_sta_list; + esp_wifi_ap_get_sta_list(&station); + tcpip_adapter_get_sta_list(&station, &tcpip_sta_list); + webPrintln("Connected clients: ", String(station.num)); - webPrintln("Authentication: ", mode); - webPrintln("Max Connections: ", String(conf.ap.max_connection)); + for (int i = 0; i < station.num; i++) { + webPrint(wifi_config.mac2str(tcpip_sta_list.sta[i].mac)); + webPrintln(" ", IPAddress(tcpip_sta_list.sta[i].ip.addr)); + } + webPrint("Disabled Mode: "); + print_mac("STA", WiFi.macAddress()); + break; + case WIFI_AP_STA: //we should not be in this state but just in case .... + webPrintln("Mixed"); - tcpip_adapter_dhcp_status_t dhcp_status; - tcpip_adapter_dhcps_get_status(TCPIP_ADAPTER_IF_AP, &dhcp_status); - webPrintln("DHCP Server: ", dhcp_status == TCPIP_ADAPTER_DHCP_STARTED ? "Started" : "Stopped"); - - webPrintln("IP: ", WiFi.softAPIP()); - - tcpip_adapter_ip_info_t ip_AP; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip_AP); - webPrintln("Gateway: ", IPAddress(ip_AP.gw.addr)); - webPrintln("Mask: ", IPAddress(ip_AP.netmask.addr)); - - wifi_sta_list_t station; - tcpip_adapter_sta_list_t tcpip_sta_list; - esp_wifi_ap_get_sta_list(&station); - tcpip_adapter_get_sta_list(&station, &tcpip_sta_list); - webPrintln("Connected clients: ", String(station.num)); - - for (int i = 0; i < station.num; i++) { - webPrint(wifi_config.mac2str(tcpip_sta_list.sta[i].mac)); - webPrintln(" ", IPAddress(tcpip_sta_list.sta[i].ip.addr)); - } - webPrint("Disabled Mode: "); - print_mac("STA", WiFi.macAddress()); - break; - case WIFI_AP_STA: //we should not be in this state but just in case .... - webPrintln("Mixed"); - - print_mac("STA", WiFi.macAddress()); - print_mac("AP", WiFi.softAPmacAddress()); - break; - default: //we should not be there if no wifi .... - webPrintln("Off"); - break; + print_mac("STA", WiFi.macAddress()); + print_mac("AP", WiFi.softAPmacAddress()); + break; + default: //we should not be there if no wifi .... + webPrintln("Off"); + break; } -#endif // ENABLE_WIFI +#endif // ENABLE_WIFI #ifdef ENABLE_BLUETOOTH webPrint("Current BT Mode: "); if (bt_config.Is_BT_on()) { @@ -588,7 +557,7 @@ static err_t showSysStats(char *parameter, auth_t auth_level) { // ESP420 } #ifdef ENABLE_WIFI -static err_t listAPs(char *parameter, auth_t auth_level) { // ESP410 +static err_t listAPs(char* parameter, auth_t auth_level) { // ESP410 JSONencoder* j = new JSONencoder(espresponse->client() != CLIENT_WEBUI); j->begin(); j->begin_array("AP_LIST"); @@ -596,8 +565,8 @@ static err_t listAPs(char *parameter, auth_t auth_level) { // ESP410 // is a good chance that scan information is already available. int n = WiFi.scanComplete(); switch (n) { - case -2: // Scan not triggered - WiFi.scanNetworks(true); // Begin async scan + case -2: // Scan not triggered + WiFi.scanNetworks(true); // Begin async scan break; case -1: // Scan in progress break; @@ -629,14 +598,14 @@ static err_t listAPs(char *parameter, auth_t auth_level) { // ESP410 } #endif -static err_t setWebSetting(char *parameter, auth_t auth_level) { // ESP401 +static err_t setWebSetting(char* parameter, auth_t auth_level) { // ESP401 // We do not need the "T=" (type) parameter because the // Setting objects know their own type if (!split_params(parameter)) { return STATUS_INVALID_VALUE; } - char *sval = get_param("V", true); - const char *spos = get_param("P", false); + char* sval = get_param("V", true); + const char* spos = get_param("P", false); if (*spos == '\0') { webPrintln("Missing parameter"); return STATUS_INVALID_VALUE; @@ -645,11 +614,11 @@ static err_t setWebSetting(char *parameter, auth_t auth_level) { // ESP401 return ret; } -static err_t listSettings(char *parameter, auth_t auth_level) { // ESP400 +static err_t listSettings(char* parameter, auth_t auth_level) { // ESP400 JSONencoder* j = new JSONencoder(espresponse->client() != CLIENT_WEBUI); j->begin(); j->begin_array("EEPROM"); - for (Setting *js = Setting::List; js; js = js->next()) { + for (Setting* js = Setting::List; js; js = js->next()) { if (js->getType() == WEBSET) { js->addWebui(j); } @@ -661,7 +630,7 @@ static err_t listSettings(char *parameter, auth_t auth_level) { // ESP400 } #ifdef ENABLE_SD_CARD -static err_t runSDFile(char *parameter, auth_t auth_level) { // ESP220 +static err_t runSDFile(char* parameter, auth_t auth_level) { // ESP220 parameter = trim(parameter); if (*parameter == '\0') { webPrintln("Missing file name!"); @@ -694,13 +663,14 @@ static err_t runSDFile(char *parameter, auth_t auth_level) { // ESP220 return STATUS_OK; } SD_client = (espresponse) ? espresponse->client() : CLIENT_ALL; - report_status_message(gc_execute_line(fileLine, (espresponse) ? espresponse->client() : CLIENT_ALL), (espresponse) ? espresponse->client() : CLIENT_ALL); // execute the first line + report_status_message(gc_execute_line(fileLine, (espresponse) ? espresponse->client() : CLIENT_ALL), + (espresponse) ? espresponse->client() : CLIENT_ALL); // execute the first line report_realtime_status((espresponse) ? espresponse->client() : CLIENT_ALL); webPrintln(""); return STATUS_OK; } -static err_t deleteSDObject(char *parameter, auth_t auth_level) { // ESP215 +static err_t deleteSDObject(char* parameter, auth_t auth_level) { // ESP215 parameter = trim(parameter); if (*parameter == '\0') { webPrintln("Missing file name!"); @@ -708,7 +678,7 @@ static err_t deleteSDObject(char *parameter, auth_t auth_level) { // ESP215 } int8_t state = get_sd_state(true); if (state != SDCARD_IDLE) { - webPrintln( (state == SDCARD_NOT_PRESENT) ? "No SD card" : "Busy"); + webPrintln((state == SDCARD_NOT_PRESENT) ? "No SD card" : "Busy"); return STATUS_OK; } String path = parameter; @@ -737,7 +707,7 @@ static err_t deleteSDObject(char *parameter, auth_t auth_level) { // ESP215 return STATUS_OK; } -static err_t listSDFiles(char *parameter, auth_t auth_level) { // ESP210 +static err_t listSDFiles(char* parameter, auth_t auth_level) { // ESP210 int8_t state = get_sd_state(true); if (state != SDCARD_IDLE) { if (state == SDCARD_NOT_PRESENT) { @@ -759,7 +729,7 @@ static err_t listSDFiles(char *parameter, auth_t auth_level) { // ESP210 } #endif -static err_t listLocalFiles(char *parameter, auth_t auth_level) { // No ESP command +static err_t listLocalFiles(char* parameter, auth_t auth_level) { // No ESP command webPrintln(""); listDir(SPIFFS, "/", 10, espresponse->client()); String ssd = "[Local FS Free:" + ESPResponseStream::formatBytes(SPIFFS.totalBytes() - SPIFFS.usedBytes()); @@ -775,7 +745,7 @@ static void listDirJSON(fs::FS& fs, const char* dirname, uint8_t levels, JSONenc File file = root.openNextFile(); while (file) { const char* tailName = strchr(file.name(), '/'); - tailName = tailName ? tailName + 1 : file.name(); + tailName = tailName ? tailName + 1 : file.name(); if (file.isDirectory() && levels) { j->begin_array(tailName); listDirJSON(fs, file.name(), levels - 1, j); @@ -790,7 +760,7 @@ static void listDirJSON(fs::FS& fs, const char* dirname, uint8_t levels, JSONenc } } -static err_t listLocalFilesJSON(char *parameter, auth_t auth_level) { // No ESP command +static err_t listLocalFilesJSON(char* parameter, auth_t auth_level) { // No ESP command JSONencoder* j = new JSONencoder(espresponse->client() != CLIENT_WEBUI); j->begin(); j->begin_array("files"); @@ -806,34 +776,31 @@ static err_t listLocalFilesJSON(char *parameter, auth_t auth_level) { // No ESP return STATUS_OK; } -static err_t showSDStatus(char *parameter, auth_t auth_level) { // ESP200 +static err_t showSDStatus(char* parameter, auth_t auth_level) { // ESP200 const char* resp = "No SD card"; #ifdef ENABLE_SD_CARD switch (get_sd_state(true)) { - case SDCARD_IDLE: - resp = "SD card detected"; - break; - case SDCARD_NOT_PRESENT: - resp = "No SD card"; - break; - default: - resp = "Busy"; + case SDCARD_IDLE: resp = "SD card detected"; break; + case SDCARD_NOT_PRESENT: resp = "No SD card"; break; + default: resp = "Busy"; } #endif webPrintln(resp); return STATUS_OK; } -static err_t setRadioState(char *parameter, auth_t auth_level) { // ESP115 +static err_t setRadioState(char* parameter, auth_t auth_level) { // ESP115 parameter = trim(parameter); if (*parameter == '\0') { // Display the radio state bool on = false; -#if defined (ENABLE_WIFI) - if (WiFi.getMode() != WIFI_MODE_NULL)on = true; +#if defined(ENABLE_WIFI) + if (WiFi.getMode() != WIFI_MODE_NULL) + on = true; #endif -#if defined (ENABLE_BLUETOOTH) - if (bt_config.Is_BT_on())on = true; +#if defined(ENABLE_BLUETOOTH) + if (bt_config.Is_BT_on()) + on = true; #endif webPrintln(on ? "ON" : "OFF"); return STATUS_OK; @@ -849,12 +816,12 @@ static err_t setRadioState(char *parameter, auth_t auth_level) { // ESP115 return STATUS_INVALID_VALUE; } //Stop everything -#if defined (ENABLE_WIFI) +#if defined(ENABLE_WIFI) if (WiFi.getMode() != WIFI_MODE_NULL) { wifi_config.StopWiFi(); } #endif -#if defined (ENABLE_BLUETOOTH) +#if defined(ENABLE_BLUETOOTH) if (bt_config.Is_BT_on()) { bt_config.end(); } @@ -867,39 +834,37 @@ static err_t setRadioState(char *parameter, auth_t auth_level) { // ESP115 //On #ifdef WIFI_OR_BLUETOOTH switch (wifi_radio_mode->get()) { - case ESP_WIFI_AP: - case ESP_WIFI_STA: - #if !defined (ENABLE_WIFI) + case ESP_WIFI_AP: + case ESP_WIFI_STA: +# if !defined(ENABLE_WIFI) webPrintln("WiFi is not enabled!"); return STATUS_WIFI_FAIL_BEGIN; - #else +# else wifi_config.begin(); return STATUS_OK; - #endif - case ESP_BT: - #if !defined (ENABLE_BLUETOOTH) +# endif + case ESP_BT: +# if !defined(ENABLE_BLUETOOTH) webPrintln("Bluetooth is not enabled!"); return STATUS_BT_FAIL_BEGIN; - #else +# else bt_config.begin(); return STATUS_OK; - #endif - default: - webPrintln("[MSG: Radio is Off]"); - return STATUS_OK; +# endif + default: webPrintln("[MSG: Radio is Off]"); return STATUS_OK; } #endif return STATUS_OK; } #ifdef ENABLE_WIFI -static err_t showIP(char *parameter, auth_t auth_level) { // ESP111 +static err_t showIP(char* parameter, auth_t auth_level) { // ESP111 webPrintln(parameter, WiFi.getMode() == WIFI_STA ? WiFi.localIP() : WiFi.softAPIP()); return STATUS_OK; } -static err_t showSetStaParams(char *parameter, auth_t auth_level) { // ESP103 +static err_t showSetStaParams(char* parameter, auth_t auth_level) { // ESP103 if (*parameter == '\0') { webPrint("IP:", wifi_sta_ip->getStringValue()); webPrint(" GW:", wifi_sta_gateway->getStringValue()); @@ -909,9 +874,9 @@ static err_t showSetStaParams(char *parameter, auth_t auth_level) { // ESP103 if (!split_params(parameter)) { return STATUS_INVALID_VALUE; } - char *gateway = get_param("GW", false); - char *netmask = get_param("MSK", false); - char *ip = get_param("IP", false); + char* gateway = get_param("GW", false); + char* netmask = get_param("MSK", false); + char* ip = get_param("IP", false); err_t err = wifi_sta_ip->setStringValue(ip); if (!err) { @@ -924,11 +889,11 @@ static err_t showSetStaParams(char *parameter, auth_t auth_level) { // ESP103 } #endif -static err_t showWebHelp(char *parameter, auth_t auth_level) { // ESP0 +static err_t showWebHelp(char* parameter, auth_t auth_level) { // ESP0 webPrintln("Persistent web settings - $name to show, $name=value to set"); webPrintln("ESPname FullName Description"); webPrintln("------- -------- -----------"); - for (Setting *s = Setting::List; s; s = s->next()) { + for (Setting* s = Setting::List; s; s = s->next()) { if (s->getType() == WEBSET) { if (s->getGrblName()) { webPrint(" ", s->getGrblName()); @@ -943,7 +908,7 @@ static err_t showWebHelp(char *parameter, auth_t auth_level) { // ESP0 webPrintln("Other web commands: $name to show, $name=value to set"); webPrintln("ESPname FullName Values"); webPrintln("------- -------- ------"); - for (Command *cp = Command::List; cp; cp = cp->next()) { + for (Command* cp = Command::List; cp; cp = cp->next()) { if (cp->getType() == WEBCMD) { if (cp->getGrblName()) { webPrint(" ", cp->getGrblName()); @@ -965,98 +930,169 @@ static err_t showWebHelp(char *parameter, auth_t auth_level) { // ESP0 // line up while allowing VSCode code folding to work correction. #define WEB_COMMON -void make_web_settings() -{ - // If authentication enabled, display_settings skips or displays - // RU - need user or admin password to read - // WU - need user or admin password to set - // WA - need admin password to set - #ifdef WEB_COMMON - new WebCommand(NULL, WEBCMD, WG, "ESP800", "Firmware/Info", showFwInfo); - new WebCommand(NULL, WEBCMD, WU, "ESP720", "LocalFS/Size", SPIFFSSize); - new WebCommand("FORMAT", WEBCMD, WA, "ESP710", "LocalFS/Format", formatSpiffs); - new WebCommand("path", WEBCMD, WU, "ESP700", "LocalFS/Run", runFile); - new WebCommand("path", WEBCMD, WU, NULL, "LocalFS/List", listLocalFiles); - new WebCommand("path", WEBCMD, WU, NULL, "LocalFS/ListJSON",listLocalFilesJSON); - #endif - #ifdef ENABLE_NOTIFICATIONS - new WebCommand("TYPE=NONE|PUSHOVER|EMAIL|LINE T1=token1 T2=token2 TS=settings", - WEBCMD, WA, "ESP610", "Notification/Setup",showSetNotification); - new WebCommand("message", WEBCMD, WU, "ESP600", "Notification/Send", sendMessage); - #endif - #ifdef ENABLE_AUTHENTICATION - new WebCommand("password",WEBCMD, WA, "ESP555", "WebUI/SetUserPassword", setUserPassword); - #endif - #ifdef WEB_COMMON - new WebCommand("RESTART", WEBCMD, WA, "ESP444", "System/Control",setSystemMode); - new WebCommand(NULL, WEBCMD, WU, "ESP420", "System/Stats", showSysStats); - #endif - #ifdef ENABLE_WIFI - new WebCommand(NULL, WEBCMD, WU, "ESP410", "WiFi/ListAPs", listAPs); - #endif - #ifdef WEB_COMMON - new WebCommand("P=position T=type V=value", - WEBCMD, WA, "ESP401", "WebUI/Set", setWebSetting); - new WebCommand(NULL, WEBCMD, WU, "ESP400", "WebUI/List", listSettings); - #endif - #ifdef ENABLE_SD_CARD - new WebCommand("path", WEBCMD, WU, "ESP220", "SD/Run", runSDFile); - new WebCommand("file_or_directory_path", - WEBCMD, WU, "ESP215", "SD/Delete", deleteSDObject); - new WebCommand(NULL, WEBCMD, WU, "ESP210", "SD/List", listSDFiles); - #endif - #ifdef WEB_COMMON - new WebCommand(NULL, WEBCMD, WU, "ESP200", "SD/Status", showSDStatus); - new WebCommand("STA|AP|BT|OFF", - WEBCMD, WA, "ESP115", "Radio/State", setRadioState); - #endif - #ifdef ENABLE_WIFI - new WebCommand(NULL, WEBCMD, WG,"ESP111", "System/IP", showIP); - new WebCommand("IP=ipaddress MSK=netmask GW=gateway", - WEBCMD, WA, "ESP103", "Sta/Setup", showSetStaParams); - #endif - #ifdef WEB_COMMON - new WebCommand(NULL, WEBCMD, WG, "ESP0", "WebUI/Help", showWebHelp); - new WebCommand(NULL, WEBCMD, WG, "ESP", "WebUI/Help", showWebHelp); - #endif - // WebUI Settings - // Standard WEBUI authentication is user+ to get, admin to set unless otherwise specified - #ifdef ENABLE_NOTIFICATIONS - notification_ts = new StringSetting("Notification Settings", WEBSET, WA, NULL, "Notification/TS", DEFAULT_TOKEN, 0, MAX_NOTIFICATION_SETTING_LENGTH, NULL); - notification_t2 = new StringSetting("Notification Token 2", WEBSET, WA, NULL, "Notification/T2", DEFAULT_TOKEN, MIN_NOTIFICATION_TOKEN_LENGTH, MAX_NOTIFICATION_TOKEN_LENGTH, NULL); - notification_t1 = new StringSetting("Notification Token 1", WEBSET, WA, NULL, "Notification/T1", DEFAULT_TOKEN , MIN_NOTIFICATION_TOKEN_LENGTH, MAX_NOTIFICATION_TOKEN_LENGTH, NULL); - notification_type = new EnumSetting("Notification type", WEBSET, WA, NULL, "Notification/Type", DEFAULT_NOTIFICATION_TYPE, ¬ificationOptions); - #endif - #ifdef ENABLE_AUTHENTICATION - user_password = new StringSetting("User password", WEBSET, WA, NULL, "WebUI/UserPassword", DEFAULT_USER_PWD, MIN_LOCAL_PASSWORD_LENGTH, MAX_LOCAL_PASSWORD_LENGTH, &COMMANDS::isLocalPasswordValid); - admin_password = new StringSetting("Admin password", WEBSET, WA, NULL, "WebUI/AdminPassword", DEFAULT_ADMIN_PWD, MIN_LOCAL_PASSWORD_LENGTH, MAX_LOCAL_PASSWORD_LENGTH, &COMMANDS::isLocalPasswordValid); - #endif - #ifdef ENABLE_BLUETOOTH - bt_name = new StringSetting("Bluetooth name", WEBSET, WA, "ESP140", "Bluetooth/Name", DEFAULT_BT_NAME, MIN_BTNAME_LENGTH, MAX_BTNAME_LENGTH, (bool (*)(char*))BTConfig::isBTnameValid); - #endif +void make_web_settings() { +// If authentication enabled, display_settings skips or displays +// RU - need user or admin password to read +// WU - need user or admin password to set +// WA - need admin password to set +#ifdef WEB_COMMON + new WebCommand(NULL, WEBCMD, WG, "ESP800", "Firmware/Info", showFwInfo); + new WebCommand(NULL, WEBCMD, WU, "ESP720", "LocalFS/Size", SPIFFSSize); + new WebCommand("FORMAT", WEBCMD, WA, "ESP710", "LocalFS/Format", formatSpiffs); + new WebCommand("path", WEBCMD, WU, "ESP700", "LocalFS/Run", runFile); + new WebCommand("path", WEBCMD, WU, NULL, "LocalFS/List", listLocalFiles); + new WebCommand("path", WEBCMD, WU, NULL, "LocalFS/ListJSON", listLocalFilesJSON); +#endif +#ifdef ENABLE_NOTIFICATIONS + new WebCommand( + "TYPE=NONE|PUSHOVER|EMAIL|LINE T1=token1 T2=token2 TS=settings", WEBCMD, WA, "ESP610", "Notification/Setup", showSetNotification); + new WebCommand("message", WEBCMD, WU, "ESP600", "Notification/Send", sendMessage); +#endif +#ifdef ENABLE_AUTHENTICATION + new WebCommand("password", WEBCMD, WA, "ESP555", "WebUI/SetUserPassword", setUserPassword); +#endif +#ifdef WEB_COMMON + new WebCommand("RESTART", WEBCMD, WA, "ESP444", "System/Control", setSystemMode); + new WebCommand(NULL, WEBCMD, WU, "ESP420", "System/Stats", showSysStats); +#endif +#ifdef ENABLE_WIFI + new WebCommand(NULL, WEBCMD, WU, "ESP410", "WiFi/ListAPs", listAPs); +#endif +#ifdef WEB_COMMON + new WebCommand("P=position T=type V=value", WEBCMD, WA, "ESP401", "WebUI/Set", setWebSetting); + new WebCommand(NULL, WEBCMD, WU, "ESP400", "WebUI/List", listSettings); +#endif +#ifdef ENABLE_SD_CARD + new WebCommand("path", WEBCMD, WU, "ESP220", "SD/Run", runSDFile); + new WebCommand("file_or_directory_path", WEBCMD, WU, "ESP215", "SD/Delete", deleteSDObject); + new WebCommand(NULL, WEBCMD, WU, "ESP210", "SD/List", listSDFiles); +#endif +#ifdef WEB_COMMON + new WebCommand(NULL, WEBCMD, WU, "ESP200", "SD/Status", showSDStatus); + new WebCommand("STA|AP|BT|OFF", WEBCMD, WA, "ESP115", "Radio/State", setRadioState); +#endif +#ifdef ENABLE_WIFI + new WebCommand(NULL, WEBCMD, WG, "ESP111", "System/IP", showIP); + new WebCommand("IP=ipaddress MSK=netmask GW=gateway", WEBCMD, WA, "ESP103", "Sta/Setup", showSetStaParams); +#endif +#ifdef WEB_COMMON + new WebCommand(NULL, WEBCMD, WG, "ESP0", "WebUI/Help", showWebHelp); + new WebCommand(NULL, WEBCMD, WG, "ESP", "WebUI/Help", showWebHelp); +#endif +// WebUI Settings +// Standard WEBUI authentication is user+ to get, admin to set unless otherwise specified +#ifdef ENABLE_NOTIFICATIONS + notification_ts = new StringSetting( + "Notification Settings", WEBSET, WA, NULL, "Notification/TS", DEFAULT_TOKEN, 0, MAX_NOTIFICATION_SETTING_LENGTH, NULL); + notification_t2 = new StringSetting("Notification Token 2", + WEBSET, + WA, + NULL, + "Notification/T2", + DEFAULT_TOKEN, + MIN_NOTIFICATION_TOKEN_LENGTH, + MAX_NOTIFICATION_TOKEN_LENGTH, + NULL); + notification_t1 = new StringSetting("Notification Token 1", + WEBSET, + WA, + NULL, + "Notification/T1", + DEFAULT_TOKEN, + MIN_NOTIFICATION_TOKEN_LENGTH, + MAX_NOTIFICATION_TOKEN_LENGTH, + NULL); + notification_type = + new EnumSetting("Notification type", WEBSET, WA, NULL, "Notification/Type", DEFAULT_NOTIFICATION_TYPE, ¬ificationOptions); +#endif +#ifdef ENABLE_AUTHENTICATION + user_password = new StringSetting("User password", + WEBSET, + WA, + NULL, + "WebUI/UserPassword", + DEFAULT_USER_PWD, + MIN_LOCAL_PASSWORD_LENGTH, + MAX_LOCAL_PASSWORD_LENGTH, + &COMMANDS::isLocalPasswordValid); + admin_password = new StringSetting("Admin password", + WEBSET, + WA, + NULL, + "WebUI/AdminPassword", + DEFAULT_ADMIN_PWD, + MIN_LOCAL_PASSWORD_LENGTH, + MAX_LOCAL_PASSWORD_LENGTH, + &COMMANDS::isLocalPasswordValid); +#endif +#ifdef ENABLE_BLUETOOTH + bt_name = new StringSetting("Bluetooth name", + WEBSET, + WA, + "ESP140", + "Bluetooth/Name", + DEFAULT_BT_NAME, + MIN_BTNAME_LENGTH, + MAX_BTNAME_LENGTH, + (bool (*)(char*))BTConfig::isBTnameValid); +#endif - #ifdef WIFI_OR_BLUETOOTH - // user+ to get, admin to set - wifi_radio_mode = new EnumSetting("Radio mode", WEBSET, WA, "ESP110", "Radio/Mode", DEFAULT_RADIO_MODE, &radioEnabledOptions); - #endif +#ifdef WIFI_OR_BLUETOOTH + // user+ to get, admin to set + wifi_radio_mode = new EnumSetting("Radio mode", WEBSET, WA, "ESP110", "Radio/Mode", DEFAULT_RADIO_MODE, &radioEnabledOptions); +#endif - #ifdef ENABLE_WIFI - telnet_port = new IntSetting("Telnet Port", WEBSET, WA, "ESP131", "Telnet/Port", DEFAULT_TELNETSERVER_PORT, MIN_TELNET_PORT, MAX_TELNET_PORT, NULL); - telnet_enable = new EnumSetting("Telnet Enable", WEBSET, WA, "ESP130", "Telnet/Enable", DEFAULT_TELNET_STATE, &onoffOptions); - http_port = new IntSetting("HTTP Port", WEBSET, WA, "ESP121", "Http/Port", DEFAULT_WEBSERVER_PORT, MIN_HTTP_PORT, MAX_HTTP_PORT, NULL); - http_enable = new EnumSetting("HTTP Enable", WEBSET, WA, "ESP120", "Http/Enable", DEFAULT_HTTP_STATE, &onoffOptions); - wifi_hostname = new StringSetting("Hostname", WEBSET, WA, "ESP112", "System/Hostname", DEFAULT_HOSTNAME, MIN_HOSTNAME_LENGTH, MAX_HOSTNAME_LENGTH, (bool (*)(char*))WiFiConfig::isHostnameValid); - wifi_ap_channel = new IntSetting("AP Channel", WEBSET, WA, "ESP108", "AP/Channel", DEFAULT_AP_CHANNEL, MIN_CHANNEL, MAX_CHANNEL, NULL); - wifi_ap_ip = new IPaddrSetting("AP Static IP", WEBSET, WA, "ESP107", "AP/IP", DEFAULT_AP_IP, NULL); - // no get, admin to set - wifi_ap_password = new StringSetting("AP Password", WEBSET, WA, "ESP106", "AP/Password", DEFAULT_AP_PWD, MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH, (bool (*)(char*))WiFiConfig::isPasswordValid); - wifi_ap_ssid = new StringSetting("AP SSID", WEBSET, WA, "ESP105", "AP/SSID", DEFAULT_AP_SSID, MIN_SSID_LENGTH, MAX_SSID_LENGTH, (bool (*)(char*))WiFiConfig::isSSIDValid); - wifi_sta_netmask = new IPaddrSetting("Station Static Mask", WEBSET, WA, NULL, "Sta/Netmask", DEFAULT_STA_MK, NULL); - wifi_sta_gateway = new IPaddrSetting("Station Static Gateway", WEBSET, WA, NULL, "Sta/Gateway", DEFAULT_STA_GW, NULL); - wifi_sta_ip = new IPaddrSetting("Station Static IP", WEBSET, WA, NULL, "Sta/IP", DEFAULT_STA_IP, NULL); - wifi_sta_mode = new EnumSetting("Station IP Mode", WEBSET, WA, "ESP102", "Sta/IPMode", DEFAULT_STA_IP_MODE, &staModeOptions); - // no get, admin to set - wifi_sta_password = new StringSetting("Station Password", WEBSET, WA, "ESP101", "Sta/Password", DEFAULT_STA_PWD, MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH, (bool (*)(char*))WiFiConfig::isPasswordValid); - wifi_sta_ssid = new StringSetting("Station SSID", WEBSET, WA, "ESP100", "Sta/SSID", DEFAULT_STA_SSID, MIN_SSID_LENGTH, MAX_SSID_LENGTH, (bool (*)(char*))WiFiConfig::isSSIDValid); - #endif +#ifdef ENABLE_WIFI + telnet_port = new IntSetting( + "Telnet Port", WEBSET, WA, "ESP131", "Telnet/Port", DEFAULT_TELNETSERVER_PORT, MIN_TELNET_PORT, MAX_TELNET_PORT, NULL); + telnet_enable = new EnumSetting("Telnet Enable", WEBSET, WA, "ESP130", "Telnet/Enable", DEFAULT_TELNET_STATE, &onoffOptions); + http_port = new IntSetting("HTTP Port", WEBSET, WA, "ESP121", "Http/Port", DEFAULT_WEBSERVER_PORT, MIN_HTTP_PORT, MAX_HTTP_PORT, NULL); + http_enable = new EnumSetting("HTTP Enable", WEBSET, WA, "ESP120", "Http/Enable", DEFAULT_HTTP_STATE, &onoffOptions); + wifi_hostname = new StringSetting("Hostname", + WEBSET, + WA, + "ESP112", + "System/Hostname", + DEFAULT_HOSTNAME, + MIN_HOSTNAME_LENGTH, + MAX_HOSTNAME_LENGTH, + (bool (*)(char*))WiFiConfig::isHostnameValid); + wifi_ap_channel = new IntSetting("AP Channel", WEBSET, WA, "ESP108", "AP/Channel", DEFAULT_AP_CHANNEL, MIN_CHANNEL, MAX_CHANNEL, NULL); + wifi_ap_ip = new IPaddrSetting("AP Static IP", WEBSET, WA, "ESP107", "AP/IP", DEFAULT_AP_IP, NULL); + // no get, admin to set + wifi_ap_password = new StringSetting("AP Password", + WEBSET, + WA, + "ESP106", + "AP/Password", + DEFAULT_AP_PWD, + MIN_PASSWORD_LENGTH, + MAX_PASSWORD_LENGTH, + (bool (*)(char*))WiFiConfig::isPasswordValid); + wifi_ap_ssid = new StringSetting( + "AP SSID", WEBSET, WA, "ESP105", "AP/SSID", DEFAULT_AP_SSID, MIN_SSID_LENGTH, MAX_SSID_LENGTH, (bool (*)(char*))WiFiConfig::isSSIDValid); + wifi_sta_netmask = new IPaddrSetting("Station Static Mask", WEBSET, WA, NULL, "Sta/Netmask", DEFAULT_STA_MK, NULL); + wifi_sta_gateway = new IPaddrSetting("Station Static Gateway", WEBSET, WA, NULL, "Sta/Gateway", DEFAULT_STA_GW, NULL); + wifi_sta_ip = new IPaddrSetting("Station Static IP", WEBSET, WA, NULL, "Sta/IP", DEFAULT_STA_IP, NULL); + wifi_sta_mode = new EnumSetting("Station IP Mode", WEBSET, WA, "ESP102", "Sta/IPMode", DEFAULT_STA_IP_MODE, &staModeOptions); + // no get, admin to set + wifi_sta_password = new StringSetting("Station Password", + WEBSET, + WA, + "ESP101", + "Sta/Password", + DEFAULT_STA_PWD, + MIN_PASSWORD_LENGTH, + MAX_PASSWORD_LENGTH, + (bool (*)(char*))WiFiConfig::isPasswordValid); + wifi_sta_ssid = new StringSetting("Station SSID", + WEBSET, + WA, + "ESP100", + "Sta/SSID", + DEFAULT_STA_SSID, + MIN_SSID_LENGTH, + MAX_SSID_LENGTH, + (bool (*)(char*))WiFiConfig::isSSIDValid); +#endif } diff --git a/Grbl_Esp32/WebSettings.h b/Grbl_Esp32/WebSettings.h index 4c01a84a..c9606364 100644 --- a/Grbl_Esp32/WebSettings.h +++ b/Grbl_Esp32/WebSettings.h @@ -37,10 +37,10 @@ extern IPaddrSetting* wifi_ap_ip; extern IntSetting* wifi_ap_channel; extern StringSetting* wifi_hostname; -extern EnumSetting* http_enable; -extern IntSetting* http_port; -extern EnumSetting* telnet_enable; -extern IntSetting* telnet_port; +extern EnumSetting* http_enable; +extern IntSetting* http_port; +extern EnumSetting* telnet_enable; +extern IntSetting* telnet_port; #endif #ifdef WIFI_OR_BLUETOOTH @@ -57,7 +57,7 @@ extern StringSetting* admin_password; #endif #ifdef ENABLE_NOTIFICATIONS -extern EnumSetting* notification_type; +extern EnumSetting* notification_type; extern StringSetting* notification_t1; extern StringSetting* notification_t2; extern StringSetting* notification_ts; diff --git a/Grbl_Esp32/authentication.cpp b/Grbl_Esp32/authentication.cpp index 59f75c6f..879288bd 100644 --- a/Grbl_Esp32/authentication.cpp +++ b/Grbl_Esp32/authentication.cpp @@ -5,9 +5,9 @@ StringSetting* user_password; StringSetting* admin_password; -void remove_password(char *str, auth_t& auth_level) { +void remove_password(char* str, auth_t& auth_level) { String paramStr = String((const char*)str); - int pos = paramStr.indexOf("pwd="); + int pos = paramStr.indexOf("pwd="); if (pos == -1) { return; } @@ -15,7 +15,7 @@ void remove_password(char *str, auth_t& auth_level) { // Truncate the str string at the pwd= . // If the pwd= is preceded by a space, take off that space too. int endpos = pos; - if (endpos && str[endpos-1] == ' ') { + if (endpos && str[endpos - 1] == ' ') { --endpos; } str[endpos] = '\0'; @@ -35,7 +35,7 @@ void remove_password(char *str, auth_t& auth_level) { } } #else -void remove_password(char *str, auth_t& auth_level) { +void remove_password(char* str, auth_t& auth_level) { auth_level = LEVEL_ADMIN; } #endif diff --git a/Grbl_Esp32/authentication.h b/Grbl_Esp32/authentication.h index 09ca20eb..3e11d797 100644 --- a/Grbl_Esp32/authentication.h +++ b/Grbl_Esp32/authentication.h @@ -1,13 +1,9 @@ #pragma once //Authentication level -typedef enum { - LEVEL_GUEST = 0, - LEVEL_USER = 1, - LEVEL_ADMIN = 2 -} auth_t; +typedef enum { LEVEL_GUEST = 0, LEVEL_USER = 1, LEVEL_ADMIN = 2 } auth_t; -#define MIN_LOCAL_PASSWORD_LENGTH 1 -#define MAX_LOCAL_PASSWORD_LENGTH 16 +#define MIN_LOCAL_PASSWORD_LENGTH 1 +#define MAX_LOCAL_PASSWORD_LENGTH 16 -void remove_password(char *str, auth_t& auth_level); +void remove_password(char* str, auth_t& auth_level); diff --git a/Grbl_Esp32/commands.cpp b/Grbl_Esp32/commands.cpp index 62791b71..833d1e5a 100644 --- a/Grbl_Esp32/commands.cpp +++ b/Grbl_Esp32/commands.cpp @@ -34,7 +34,7 @@ bool COMMANDS::restart_ESP_module = false; */ void COMMANDS::wait(uint32_t milliseconds) { uint32_t timeout = millis(); - esp_task_wdt_reset(); //for a wait 0; + esp_task_wdt_reset(); //for a wait 0; //wait feeding WDT while ((millis() - timeout) < milliseconds) esp_task_wdt_reset(); @@ -69,6 +69,7 @@ void COMMANDS::handle() { //in case of restart requested if (restart_ESP_module) { ESP.restart(); - while (1) ; + while (1) + ; } } diff --git a/Grbl_Esp32/commands.h b/Grbl_Esp32/commands.h index 6733dcc2..1cf4594f 100644 --- a/Grbl_Esp32/commands.h +++ b/Grbl_Esp32/commands.h @@ -25,11 +25,12 @@ class ESPResponseStream; class COMMANDS { - public: +public: static void wait(uint32_t milliseconds); static void handle(); static void restart_ESP(); static bool isLocalPasswordValid(char* password); - private : + +private: static bool restart_ESP_module; }; diff --git a/Grbl_Esp32/config.h b/Grbl_Esp32/config.h index 0800c570..d1f4aa03 100644 --- a/Grbl_Esp32/config.h +++ b/Grbl_Esp32/config.h @@ -62,7 +62,7 @@ Some features should not be changed. See notes below. // NOTE: Defaults are set for a traditional 3-axis CNC machine. Z-axis first to clear, followed by X & Y. // These homing cycle definitions precede the machine.h file so that the machine // definition can undefine them if necessary. -#define HOMING_CYCLE_0 bit(Z_AXIS) // TYPICALLY REQUIRED: First move Z to clear workspace. +#define HOMING_CYCLE_0 bit(Z_AXIS) // TYPICALLY REQUIRED: First move Z to clear workspace. #define HOMING_CYCLE_1 bit(X_AXIS) #define HOMING_CYCLE_2 bit(Y_AXIS) @@ -74,10 +74,10 @@ Some features should not be changed. See notes below. // normally-closed switches on the specified pins, rather than the default normally-open switches. // The mask order is Cycle Start | Feed Hold | Reset | Safety Door // For example B1101 will invert the function of the Reset pin. -#define INVERT_CONTROL_PIN_MASK B1111 +#define INVERT_CONTROL_PIN_MASK B1111 -#define ENABLE_CONTROL_SW_DEBOUNCE // Default disabled. Uncomment to enable. -#define CONTROL_SW_DEBOUNCE_PERIOD 32 // in milliseconds default 32 microseconds +#define ENABLE_CONTROL_SW_DEBOUNCE // Default disabled. Uncomment to enable. +#define CONTROL_SW_DEBOUNCE_PERIOD 32 // in milliseconds default 32 microseconds #define USE_RMT_STEPS @@ -93,15 +93,15 @@ Some features should not be changed. See notes below. // Number of axes defined (steppers, servos, etc) (valid range: 3 to 6) // Even if your machine only uses less than the minimum of 3, you should select 3 #ifndef N_AXIS - #define N_AXIS 3 +# define N_AXIS 3 #endif #ifndef LIMIT_MASK - #define LIMIT_MASK B0 +# define LIMIT_MASK B0 #endif -#define VERBOSE_HELP // Currently this doesn't do anything -#define GRBL_MSG_LEVEL MSG_LEVEL_INFO // what level of [MSG:....] do you want to see 0=all off +#define VERBOSE_HELP // Currently this doesn't do anything +#define GRBL_MSG_LEVEL MSG_LEVEL_INFO // what level of [MSG:....] do you want to see 0=all off // Serial baud rate // OK to change, but the ESP32 boot text is 115200, so you will not see that is your @@ -112,24 +112,23 @@ Some features should not be changed. See notes below. //#define CONNECT_TO_SSID "your SSID" //#define SSID_PASSWORD "your SSID password" //CONFIGURE_EYECATCH_BEGIN (DO NOT MODIFY THIS LINE) -#define ENABLE_BLUETOOTH // enable bluetooth +#define ENABLE_BLUETOOTH // enable bluetooth -#define ENABLE_SD_CARD // enable use of SD Card to run jobs +#define ENABLE_SD_CARD // enable use of SD Card to run jobs -#define ENABLE_WIFI //enable wifi +#define ENABLE_WIFI //enable wifi #if defined(ENABLE_WIFI) || defined(ENABLE_BLUETOOTH) -#define WIFI_OR_BLUETOOTH +# define WIFI_OR_BLUETOOTH #endif - -#define ENABLE_HTTP //enable HTTP and all related services -#define ENABLE_OTA //enable OTA -#define ENABLE_TELNET //enable telnet -#define ENABLE_TELNET_WELCOME_MSG //display welcome string when connect to telnet -#define ENABLE_MDNS //enable mDNS discovery -#define ENABLE_SSDP //enable UPNP discovery -#define ENABLE_NOTIFICATIONS //enable notifications +#define ENABLE_HTTP //enable HTTP and all related services +#define ENABLE_OTA //enable OTA +#define ENABLE_TELNET //enable telnet +#define ENABLE_TELNET_WELCOME_MSG //display welcome string when connect to telnet +#define ENABLE_MDNS //enable mDNS discovery +#define ENABLE_SSDP //enable UPNP discovery +#define ENABLE_NOTIFICATIONS //enable notifications #define ENABLE_SERIAL2SOCKET_IN #define ENABLE_SERIAL2SOCKET_OUT @@ -150,32 +149,32 @@ Some features should not be changed. See notes below. #define NAMESPACE "GRBL" #ifdef ENABLE_AUTHENTICATION - #define DEFAULT_ADMIN_PWD "admin" - #define DEFAULT_USER_PWD "user" - #define DEFAULT_ADMIN_LOGIN "admin" - #define DEFAULT_USER_LOGIN "user" +# define DEFAULT_ADMIN_PWD "admin" +# define DEFAULT_USER_PWD "user" +# define DEFAULT_ADMIN_LOGIN "admin" +# define DEFAULT_USER_LOGIN "user" #endif //Radio Mode #define ESP_RADIO_OFF 0 #define ESP_WIFI_STA 1 -#define ESP_WIFI_AP 2 -#define ESP_BT 3 +#define ESP_WIFI_AP 2 +#define ESP_BT 3 //Default mode #ifdef ENABLE_WIFI - #ifdef CONNECT_TO_SSID - #define DEFAULT_RADIO_MODE ESP_WIFI_STA - #else - #define DEFAULT_RADIO_MODE ESP_WIFI_AP - #endif //CONNECT_TO_SSID +# ifdef CONNECT_TO_SSID +# define DEFAULT_RADIO_MODE ESP_WIFI_STA +# else +# define DEFAULT_RADIO_MODE ESP_WIFI_AP +# endif //CONNECT_TO_SSID #else - #undef ENABLE_NOTIFICATIONS - #ifdef ENABLE_BLUETOOTH - #define DEFAULT_RADIO_MODE ESP_BT - #else - #define DEFAULT_RADIO_MODE ESP_RADIO_OFF - #endif +# undef ENABLE_NOTIFICATIONS +# ifdef ENABLE_BLUETOOTH +# define DEFAULT_RADIO_MODE ESP_BT +# else +# define DEFAULT_RADIO_MODE ESP_RADIO_OFF +# endif #endif // Define realtime command special characters. These characters are 'picked-off' directly from the @@ -185,7 +184,7 @@ Some features should not be changed. See notes below. // g-code programs, maybe selected for interface programs. // NOTE: If changed, manually update help message in report.c. -#define CMD_RESET 0x18 // ctrl-x. +#define CMD_RESET 0x18 // ctrl-x. #define CMD_STATUS_REPORT '?' #define CMD_CYCLE_START '~' #define CMD_FEED_HOLD '!' @@ -199,19 +198,19 @@ Some features should not be changed. See notes below. // #define CMD_CYCLE_START 0x82 // #define CMD_FEED_HOLD 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_FEED_OVR_RESET 0x90 // Restores feed override value to 100%. +#define CMD_JOG_CANCEL 0x85 +#define CMD_DEBUG_REPORT 0x86 // Only when DEBUG enabled, sends debug report in '{}' braces. +#define CMD_FEED_OVR_RESET 0x90 // Restores feed override value to 100%. #define CMD_FEED_OVR_COARSE_PLUS 0x91 #define CMD_FEED_OVR_COARSE_MINUS 0x92 -#define CMD_FEED_OVR_FINE_PLUS 0x93 -#define CMD_FEED_OVR_FINE_MINUS 0x94 -#define CMD_RAPID_OVR_RESET 0x95 // Restores rapid override value to 100%. +#define CMD_FEED_OVR_FINE_PLUS 0x93 +#define CMD_FEED_OVR_FINE_MINUS 0x94 +#define CMD_RAPID_OVR_RESET 0x95 // Restores rapid override value to 100%. #define CMD_RAPID_OVR_MEDIUM 0x96 #define CMD_RAPID_OVR_LOW 0x97 // #define CMD_RAPID_OVR_EXTRA_LOW 0x98 // *NOT SUPPORTED* -#define CMD_SPINDLE_OVR_RESET 0x99 // Restores spindle override value to 100%. -#define CMD_SPINDLE_OVR_COARSE_PLUS 0x9A // 154 +#define CMD_SPINDLE_OVR_RESET 0x99 // Restores spindle override value to 100%. +#define CMD_SPINDLE_OVR_COARSE_PLUS 0x9A // 154 #define CMD_SPINDLE_OVR_COARSE_MINUS 0x9B #define CMD_SPINDLE_OVR_FINE_PLUS 0x9C #define CMD_SPINDLE_OVR_FINE_MINUS 0x9D @@ -222,18 +221,18 @@ Some features should not be changed. See notes below. // If homing is enabled, homing init lock sets Grbl into an alarm state upon power up. This forces // the user to perform the homing cycle (or override the locks) before doing anything else. This is // mainly a safety feature to remind the user to home, since position is unknown to Grbl. -#define HOMING_INIT_LOCK // Comment to disable +#define HOMING_INIT_LOCK // Comment to disable // Number of homing cycles performed after when the machine initially jogs to limit switches. // This help in preventing overshoot and should improve repeatability. This value should be one or // greater. -#define N_HOMING_LOCATE_CYCLE 1 // Integer (1-128) +#define N_HOMING_LOCATE_CYCLE 1 // Integer (1-128) // Enables single axis homing commands. $HX, $HY, and $HZ for X, Y, and Z-axis homing. The full homing // cycle is still invoked by the $H command. This is disabled by default. It's here only to address // users that need to switch between a two-axis and three-axis machine. This is actually very rare. // If you have a two-axis machine, DON'T USE THIS. Instead, just alter the homing cycle for two-axes. -#define HOMING_SINGLE_AXIS_COMMANDS // Default disabled. Uncomment to enable. +#define HOMING_SINGLE_AXIS_COMMANDS // Default disabled. Uncomment to enable. // After homing, Grbl will set by default the entire machine space into negative space, as is typical // for professional CNC machines, regardless of where the limit switches are located. Uncomment this @@ -250,7 +249,7 @@ Some features should not be changed. See notes below. // 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) +#define N_STARTUP_LINE 2 // Integer (1-2) // Number of floating decimal points printed by Grbl for certain value types. These settings are // determined by realistic and commonly observed values in CNC machines. For example, position @@ -258,12 +257,12 @@ Some features should not be changed. See notes below. // 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. // ESP32 Note: These are mostly hard coded, so these values will not change anything -#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 // Decimals for floating point setting values -#define N_DECIMAL_RPMVALUE 0 // RPM value in rotations per min. +#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 // Decimals for floating point setting values +#define N_DECIMAL_RPMVALUE 0 // RPM value in rotations per min. // If your machine has two limits switches wired in parallel to one axis, you will need to enable // this feature. Since the two switches are sharing a single pin, there is no way for Grbl to tell @@ -280,7 +279,7 @@ Some features should not be changed. See notes below. // Upon a successful probe cycle, this option provides immediately feedback of the probe coordinates // through an automatically generated message. If disabled, users can still access the last probe // coordinates through Grbl '$#' print parameters. -#define MESSAGE_PROBE_COORDINATES // Enabled by default. Comment to disable. +#define MESSAGE_PROBE_COORDINATES // Enabled by default. Comment to disable. // Enables a second coolant control pin via the mist coolant g-code command M7 on the Arduino Uno // analog pin 4. Only use this option if you require a second coolant control pin. @@ -293,12 +292,12 @@ Some features should not be changed. See notes below. // immediately forces a feed hold and then safely de-energizes the machine. Resuming is blocked until // the safety door is re-engaged. When it is, Grbl will re-energize the machine and then resume on the // previous tool path, as if nothing happened. -#define ENABLE_SAFETY_DOOR_INPUT_PIN // ESP32 Leave this enabled for now .. code for undefined not ready +#define ENABLE_SAFETY_DOOR_INPUT_PIN // ESP32 Leave this enabled for now .. code for undefined not ready // After the safety door switch has been toggled and restored, this setting sets the power-up delay // between restoring the spindle and coolant and resuming the cycle. -#define SAFETY_DOOR_SPINDLE_DELAY 4.0 // Float (seconds) -#define SAFETY_DOOR_COOLANT_DELAY 1.0 // Float (seconds) +#define SAFETY_DOOR_SPINDLE_DELAY 4.0 // Float (seconds) +#define SAFETY_DOOR_COOLANT_DELAY 1.0 // Float (seconds) // Enable CoreXY kinematics. Use ONLY with CoreXY machines. // IMPORTANT: If homing is enabled, you must reconfigure the homing cycle #defines above to @@ -352,27 +351,27 @@ Some features should not be changed. See notes below. // 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_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 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 DEFAULT_SPINDLE_SPEED_OVERRIDE 100 // 100%. Don't change this value. -#define MAX_SPINDLE_SPEED_OVERRIDE 200 // Percent of programmed spindle speed (100-255). Usually 200%. -#define MIN_SPINDLE_SPEED_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%. +#define DEFAULT_SPINDLE_SPEED_OVERRIDE 100 // 100%. Don't change this value. +#define MAX_SPINDLE_SPEED_OVERRIDE 200 // Percent of programmed spindle speed (100-255). Usually 200%. +#define MIN_SPINDLE_SPEED_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%. // When a M2 or M30 program end command is executed, most g-code states are restored to their defaults. // This compile-time option includes the restoring of the feed, rapid, and spindle speed override values // to their default values at program end. -#define RESTORE_OVERRIDES_AFTER_PROGRAM_END // Default enabled. Comment to disable. +#define RESTORE_OVERRIDES_AFTER_PROGRAM_END // Default enabled. Comment to disable. // The status report change for Grbl v1.1 and after also removed the ability to disable/enable most data // fields from the report. This caused issues for GUI developers, who've had to manage several scenarios @@ -380,12 +379,12 @@ Some features should not be changed. See notes below. // be sent without potential performance issues. // NOTE: The options below are here only provide a way to disable certain data fields if a unique // situation demands it, but be aware GUIs may depend on this data. If disabled, it may not be compatible. -#define REPORT_FIELD_BUFFER_STATE // Default enabled. Comment to disable. -#define REPORT_FIELD_PIN_STATE // Default enabled. Comment to disable. -#define REPORT_FIELD_CURRENT_FEED_SPEED // Default enabled. Comment to disable. -#define REPORT_FIELD_WORK_COORD_OFFSET // Default enabled. Comment to disable. -#define REPORT_FIELD_OVERRIDES // Default enabled. Comment to disable. -#define REPORT_FIELD_LINE_NUMBERS // Default enabled. Comment to disable. +#define REPORT_FIELD_BUFFER_STATE // Default enabled. Comment to disable. +#define REPORT_FIELD_PIN_STATE // Default enabled. Comment to disable. +#define REPORT_FIELD_CURRENT_FEED_SPEED // Default enabled. Comment to disable. +#define REPORT_FIELD_WORK_COORD_OFFSET // Default enabled. Comment to disable. +#define REPORT_FIELD_OVERRIDES // Default enabled. Comment to disable. +#define REPORT_FIELD_LINE_NUMBERS // Default enabled. Comment to disable. // 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 @@ -444,14 +443,14 @@ Some features should not be changed. See notes below. // 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. -#define TOOL_LENGTH_OFFSET_AXIS Z_AXIS // Default z-axis. Valid values are X_AXIS, Y_AXIS, or Z_AXIS. +#define TOOL_LENGTH_OFFSET_AXIS Z_AXIS // Default z-axis. Valid values are X_AXIS, Y_AXIS, or Z_AXIS. // Alters the behavior of the spindle enable pin. By default Grbl will not disable the enable pin if // spindle speed is zero and M3/4 is active, but still sets the PWM output to zero. This allows the users // to know if the spindle is active and use it as an additional control input. // However, in some use cases, user may want the enable pin to disable with a zero spindle speed and // re-enable when spindle speed is greater than zero. This option does that. -#define SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED // Default enabled. Comment to disable. +#define SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED // Default enabled. Comment to disable. // 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 @@ -474,19 +473,19 @@ Some features should not be changed. See notes below. // limits or angle between neighboring block line move directions. This is useful for machines that can't // tolerate the tool dwelling for a split second, i.e. 3d printers or laser cutters. If used, this value // should not be much greater than zero or to the minimum value necessary for the machine to work. -#define MINIMUM_JUNCTION_SPEED 0.0 // (mm/min) +#define MINIMUM_JUNCTION_SPEED 0.0 // (mm/min) // Sets the minimum feed rate the planner will allow. Any value below it will be set to this minimum // value. This also ensures that a planned motion always completes and accounts for any floating-point // round-off errors. Although not recommended, a lower value than 1.0 mm/min will likely work in smaller // machines, perhaps to 0.1mm/min, but your success may vary based on multiple factors. -#define MINIMUM_FEED_RATE 1.0 // (mm/min) +#define MINIMUM_FEED_RATE 1.0 // (mm/min) // Number of arc generation iterations by small angle approximation before exact arc trajectory // correction with expensive sin() and cos() calcualtions. This parameter maybe decreased if there // are issues with the accuracy of the arc generations, or increased if arc execution is getting // bogged down by too many trig calculations. -#define N_ARC_CORRECTION 12 // Integer (1-255) +#define N_ARC_CORRECTION 12 // Integer (1-255) // The arc G2/3 g-code standard is problematic by definition. Radius-based arcs have horrible numerical // errors when arc at semi-circles(pi) or full-circles(2*pi). Offset-based arcs are much more accurate @@ -496,15 +495,14 @@ Some features should not be changed. See notes below. // This define value sets the machine epsilon cutoff to determine if the arc is a full-circle or not. // NOTE: Be very careful when adjusting this value. It should always be greater than 1.2e-7 but not too // much greater than this. The default setting should capture most, if not all, full arc error situations. -#define ARC_ANGULAR_TRAVEL_EPSILON 5E-7 // Float (radians) +#define ARC_ANGULAR_TRAVEL_EPSILON 5E-7 // Float (radians) // Time delay increments performed during a dwell. The default value is set at 50ms, which provides // a maximum time delay of roughly 55 minutes, more than enough for most any application. Increasing // this delay will increase the maximum dwell time linearly, but also reduces the responsiveness of // run-time command executions, like status reports, since these are performed between each dwell // time step. Also, keep in mind that the Arduino delay timer is not very accurate for long delays. -#define DWELL_TIME_STEP 50 // Integer (1-255) (milliseconds) - +#define DWELL_TIME_STEP 50 // Integer (1-255) (milliseconds) // For test use only. This uses the ESP32's RMT peripheral to generate step pulses // It allows the use of the STEP_PULSE_DELAY (see below) and it automatically ends the @@ -568,7 +566,7 @@ Some features should not be changed. See notes below. // switch interrupt unblock a waiting task which will recheck the limit switch pins after // a short delay. Default disabled //#define ENABLE_SOFTWARE_DEBOUNCE // Default disabled. Uncomment to enable. -#define DEBOUNCE_PERIOD 32 // in milliseconds default 32 microseconds +#define DEBOUNCE_PERIOD 32 // in milliseconds default 32 microseconds // Configures the position after a probing cycle during Grbl's check mode. Disabled sets // the position to the probe target, when enabled sets the position to the start position. @@ -597,9 +595,9 @@ Some features should not be changed. See notes below. // Enable the '$RST=*', '$RST=$', and '$RST=#' eeprom restore commands. There are cases where // these commands may be undesirable. Simply comment the desired macro to disable it. // NOTE: See SETTINGS_RESTORE_ALL macro for customizing the `$RST=*` command. -#define ENABLE_RESTORE_EEPROM_WIPE_ALL // '$RST=*' Default enabled. Comment to disable. -#define ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS // '$RST=$' Default enabled. Comment to disable. -#define ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS // '$RST=#' Default enabled. Comment to disable. +#define ENABLE_RESTORE_EEPROM_WIPE_ALL // '$RST=*' Default enabled. Comment to disable. +#define ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS // '$RST=$' Default enabled. Comment to disable. +#define ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS // '$RST=#' Default enabled. Comment to disable. // Defines the EEPROM data restored upon a settings version change and `$RST=*` command. Whenever the // the settings or other EEPROM data structure changes between Grbl versions, Grbl will automatically @@ -622,7 +620,7 @@ Some features should not be changed. See notes below. // NOTE: If disabled and to ensure Grbl can never alter the build info line, you'll also need to enable // the SETTING_RESTORE_ALL macro above and remove SETTINGS_RESTORE_BUILD_INFO from the mask. // NOTE: See the included grblWrite_BuildInfo.ino example file to write this string seperately. -#define ENABLE_BUILD_INFO_WRITE_COMMAND // '$I=' Default enabled. Comment to disable. +#define ENABLE_BUILD_INFO_WRITE_COMMAND // '$I=' Default enabled. Comment to disable. // AVR processors require all interrupts to be disabled during an EEPROM write. This includes both // the stepper ISRs and serial comm ISRs. In the event of a long EEPROM write, this ISR pause can @@ -636,7 +634,7 @@ Some features should not be changed. See notes below. // NOTE: Most EEPROM write commands are implicitly blocked during a job (all '$' commands). However, // coordinate set g-code commands (G10,G28/30.1) are not, since they are part of an active streaming // job. At this time, this option only forces a planner buffer sync with these g-code commands. -#define FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE // Default enabled. Comment to disable. +#define FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE // Default enabled. Comment to disable. // In Grbl v0.9 and prior, there is an old outstanding bug where the `WPos:` work position reported // may not correlate to what is executing, because `WPos:` is based on the g-code parser state, which @@ -644,7 +642,7 @@ Some features should not be changed. See notes below. // motion whenever there is a command that alters the work coordinate offsets `G10,G43.1,G92,G54-59`. // This is the simplest way to ensure `WPos:` is always correct. Fortunately, it's exceedingly rare // that any of these commands are used need continuous motions through them. -#define FORCE_BUFFER_SYNC_DURING_WCO_CHANGE // Default enabled. Comment to disable. +#define FORCE_BUFFER_SYNC_DURING_WCO_CHANGE // Default enabled. Comment to disable. // By default, Grbl disables feed rate overrides for all G38.x probe cycle commands. Although this // may be different than some pro-class machine control, it's arguable that it should be this way. @@ -669,11 +667,11 @@ Some features should not be changed. See notes below. //#define PARKING_ENABLE // Default disabled. Uncomment to enable // Configure options for the parking motion, if enabled. -#define PARKING_AXIS Z_AXIS // Define which axis that performs the parking motion -#define PARKING_TARGET -5.0 // Parking axis target. In mm, as machine coordinate [-max_travel,0]. -#define PARKING_RATE 500.0 // Parking fast rate after pull-out in mm/min. -#define PARKING_PULLOUT_RATE 100.0 // Pull-out/plunge slow feed rate in mm/min. -#define PARKING_PULLOUT_INCREMENT 5.0 // Spindle pull-out and plunge distance in mm. Incremental distance. +#define PARKING_AXIS Z_AXIS // Define which axis that performs the parking motion +#define PARKING_TARGET -5.0 // Parking axis target. In mm, as machine coordinate [-max_travel,0]. +#define PARKING_RATE 500.0 // Parking fast rate after pull-out in mm/min. +#define PARKING_PULLOUT_RATE 100.0 // Pull-out/plunge slow feed rate in mm/min. +#define PARKING_PULLOUT_INCREMENT 5.0 // Spindle pull-out and plunge distance in mm. Incremental distance. // Must be positive value or equal to zero. // Enables a special set of M-code commands that enables and disables the parking motion. @@ -689,7 +687,7 @@ Some features should not be changed. See notes below. // override immediately after coming to a stop. However, this also means that the laser still may // be reenabled by disabling the spindle stop override, if needed. This is purely a safety feature // to ensure the laser doesn't inadvertently remain powered while at a stop and cause a fire. -#define DISABLE_LASER_DURING_HOLD // Default enabled. Comment to disable. +#define DISABLE_LASER_DURING_HOLD // Default enabled. Comment to disable. // Enables a piecewise linear model of the spindle PWM/speed output. Requires a solution by the // 'fit_nonlinear_spindle.py' script in the /doc/script folder of the repo. See file comments diff --git a/Grbl_Esp32/coolant_control.cpp b/Grbl_Esp32/coolant_control.cpp index 3661fecf..3259513e 100644 --- a/Grbl_Esp32/coolant_control.cpp +++ b/Grbl_Esp32/coolant_control.cpp @@ -23,7 +23,6 @@ #include "grbl.h" - void coolant_init() { #ifdef COOLANT_FLOOD_PIN pinMode(COOLANT_FLOOD_PIN, OUTPUT); @@ -34,88 +33,86 @@ void coolant_init() { coolant_stop(); } - // Returns current coolant output state. Overrides may alter it from programmed state. uint8_t coolant_get_state() { uint8_t cl_state = COOLANT_STATE_DISABLE; #ifdef COOLANT_FLOOD_PIN -#ifdef INVERT_COOLANT_FLOOD_PIN - if (! digitalRead(COOLANT_FLOOD_PIN)) { -#else +# ifdef INVERT_COOLANT_FLOOD_PIN + if (!digitalRead(COOLANT_FLOOD_PIN)) { +# else if (digitalRead(COOLANT_FLOOD_PIN)) { -#endif +# endif cl_state |= COOLANT_STATE_FLOOD; } #endif #ifdef COOLANT_MIST_PIN -#ifdef INVERT_COOLANT_MIST_PIN - if (! digitalRead(COOLANT_MIST_PIN)) { -#else +# ifdef INVERT_COOLANT_MIST_PIN + if (!digitalRead(COOLANT_MIST_PIN)) { +# else if (digitalRead(COOLANT_MIST_PIN)) { -#endif +# endif cl_state |= COOLANT_STATE_MIST; } #endif return (cl_state); } - // Directly called by coolant_init(), coolant_set_state(), and mc_reset(), which can be at // an interrupt-level. No report flag set, but only called by routines that don't need it. void coolant_stop() { #ifdef COOLANT_FLOOD_PIN -#ifdef INVERT_COOLANT_FLOOD_PIN +# ifdef INVERT_COOLANT_FLOOD_PIN digitalWrite(COOLANT_FLOOD_PIN, 1); -#else +# else digitalWrite(COOLANT_FLOOD_PIN, 0); -#endif +# endif #endif #ifdef COOLANT_MIST_PIN -#ifdef INVERT_COOLANT_MIST_PIN +# ifdef INVERT_COOLANT_MIST_PIN digitalWrite(COOLANT_MIST_PIN, 1); -#else +# else digitalWrite(COOLANT_MIST_PIN, 0); -#endif +# endif #endif } - // 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(uint8_t mode) { - if (sys.abort) return; // Block during abort. + if (sys.abort) + return; // Block during abort. if (mode == COOLANT_DISABLE) coolant_stop(); else { #ifdef COOLANT_FLOOD_PIN if (mode & COOLANT_FLOOD_ENABLE) { -#ifdef INVERT_COOLANT_FLOOD_PIN +# ifdef INVERT_COOLANT_FLOOD_PIN digitalWrite(COOLANT_FLOOD_PIN, 0); -#else +# else digitalWrite(COOLANT_FLOOD_PIN, 1); -#endif +# endif } #endif #ifdef COOLANT_MIST_PIN if (mode & COOLANT_MIST_ENABLE) { -#ifdef INVERT_COOLANT_MIST_PIN +# ifdef INVERT_COOLANT_MIST_PIN digitalWrite(COOLANT_MIST_PIN, 0); -#else +# else digitalWrite(COOLANT_MIST_PIN, 1); -#endif +# endif } #endif } - sys.report_ovr_counter = 0; // Set to report change immediately + sys.report_ovr_counter = 0; // 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. void coolant_sync(uint8_t mode) { - if (sys.state == STATE_CHECK_MODE) return; - protocol_buffer_synchronize(); // Ensure coolant turns on when specified in program. + if (sys.state == STATE_CHECK_MODE) + return; + protocol_buffer_synchronize(); // Ensure coolant turns on when specified in program. coolant_set_state(mode); } diff --git a/Grbl_Esp32/coolant_control.h b/Grbl_Esp32/coolant_control.h index f9933b73..f5fb2852 100644 --- a/Grbl_Esp32/coolant_control.h +++ b/Grbl_Esp32/coolant_control.h @@ -23,13 +23,12 @@ along with Grbl. If not, see . */ -#define COOLANT_NO_SYNC false -#define COOLANT_FORCE_SYNC true - -#define COOLANT_STATE_DISABLE 0 // Must be zero -#define COOLANT_STATE_FLOOD bit(0) -#define COOLANT_STATE_MIST bit(1) +#define COOLANT_NO_SYNC false +#define COOLANT_FORCE_SYNC true +#define COOLANT_STATE_DISABLE 0 // Must be zero +#define COOLANT_STATE_FLOOD bit(0) +#define COOLANT_STATE_MIST bit(1) // Initializes coolant control pins. void coolant_init(); diff --git a/Grbl_Esp32/custom_code.cpp b/Grbl_Esp32/custom_code.cpp index dc6ab41f..9501a93c 100644 --- a/Grbl_Esp32/custom_code.cpp +++ b/Grbl_Esp32/custom_code.cpp @@ -4,5 +4,5 @@ #include "grbl.h" #ifdef CUSTOM_CODE_FILENAME - #include CUSTOM_CODE_FILENAME +# include CUSTOM_CODE_FILENAME #endif diff --git a/Grbl_Esp32/defaults.h b/Grbl_Esp32/defaults.h index a9f9afbf..7aa5a174 100644 --- a/Grbl_Esp32/defaults.h +++ b/Grbl_Esp32/defaults.h @@ -30,406 +30,403 @@ your nefarious needs. NOTE: Ensure one and only one of these DEFAULTS_XXX values is defined in config.h */ - /* +/* All of these settings check to see if they have been defined already before defining them. This allows to to easily set them eslewhere. You only need to set ones that are important or unique to your machine. The rest will be pulled from here. */ - // Grbl generic default settings. Should work across different machines. - #ifndef DEFAULT_STEP_PULSE_MICROSECONDS - #define DEFAULT_STEP_PULSE_MICROSECONDS 3 // $0 - #endif +// Grbl generic default settings. Should work across different machines. +#ifndef DEFAULT_STEP_PULSE_MICROSECONDS +# define DEFAULT_STEP_PULSE_MICROSECONDS 3 // $0 +#endif - #ifndef DEFAULT_STEPPER_IDLE_LOCK_TIME - #define DEFAULT_STEPPER_IDLE_LOCK_TIME 250 // $1 msec (0-254, 255 keeps steppers enabled) - #endif +#ifndef DEFAULT_STEPPER_IDLE_LOCK_TIME +# define DEFAULT_STEPPER_IDLE_LOCK_TIME 250 // $1 msec (0-254, 255 keeps steppers enabled) +#endif - #ifndef DEFAULT_STEPPING_INVERT_MASK - #define DEFAULT_STEPPING_INVERT_MASK 0 // $2 uint8_t - #endif +#ifndef DEFAULT_STEPPING_INVERT_MASK +# define DEFAULT_STEPPING_INVERT_MASK 0 // $2 uint8_t +#endif - #ifndef DEFAULT_DIRECTION_INVERT_MASK - #define DEFAULT_DIRECTION_INVERT_MASK 0 // $3 uint8_ - #endif +#ifndef DEFAULT_DIRECTION_INVERT_MASK +# define DEFAULT_DIRECTION_INVERT_MASK 0 // $3 uint8_ +#endif - #ifndef DEFAULT_INVERT_ST_ENABLE - #define DEFAULT_INVERT_ST_ENABLE 0 // $4 boolean - #endif +#ifndef DEFAULT_INVERT_ST_ENABLE +# define DEFAULT_INVERT_ST_ENABLE 0 // $4 boolean +#endif - #ifndef DEFAULT_INVERT_LIMIT_PINS - #define DEFAULT_INVERT_LIMIT_PINS 1 // $5 boolean - #endif +#ifndef DEFAULT_INVERT_LIMIT_PINS +# define DEFAULT_INVERT_LIMIT_PINS 1 // $5 boolean +#endif - #ifndef DEFAULT_INVERT_PROBE_PIN - #define DEFAULT_INVERT_PROBE_PIN 0 // $6 boolean - #endif +#ifndef DEFAULT_INVERT_PROBE_PIN +# define DEFAULT_INVERT_PROBE_PIN 0 // $6 boolean +#endif - #ifndef DEFAULT_STATUS_REPORT_MASK - #define DEFAULT_STATUS_REPORT_MASK 1 // $10 - #endif +#ifndef DEFAULT_STATUS_REPORT_MASK +# define DEFAULT_STATUS_REPORT_MASK 1 // $10 +#endif - #ifndef DEFAULT_JUNCTION_DEVIATION - #define DEFAULT_JUNCTION_DEVIATION 0.01 // $11 mm - #endif +#ifndef DEFAULT_JUNCTION_DEVIATION +# define DEFAULT_JUNCTION_DEVIATION 0.01 // $11 mm +#endif - #ifndef DEFAULT_ARC_TOLERANCE - #define DEFAULT_ARC_TOLERANCE 0.002 // $12 mm - #endif +#ifndef DEFAULT_ARC_TOLERANCE +# define DEFAULT_ARC_TOLERANCE 0.002 // $12 mm +#endif - #ifndef DEFAULT_REPORT_INCHES - #define DEFAULT_REPORT_INCHES 0 // $13 false - #endif +#ifndef DEFAULT_REPORT_INCHES +# define DEFAULT_REPORT_INCHES 0 // $13 false +#endif - #ifndef DEFAULT_SOFT_LIMIT_ENABLE - #define DEFAULT_SOFT_LIMIT_ENABLE 0 // $20 false - #endif +#ifndef DEFAULT_SOFT_LIMIT_ENABLE +# define DEFAULT_SOFT_LIMIT_ENABLE 0 // $20 false +#endif - #ifndef DEFAULT_HARD_LIMIT_ENABLE - #define DEFAULT_HARD_LIMIT_ENABLE 0 // $21 false - #endif +#ifndef DEFAULT_HARD_LIMIT_ENABLE +# define DEFAULT_HARD_LIMIT_ENABLE 0 // $21 false +#endif - #ifndef DEFAULT_HOMING_ENABLE - #define DEFAULT_HOMING_ENABLE 0 // $22 false - #endif +#ifndef DEFAULT_HOMING_ENABLE +# define DEFAULT_HOMING_ENABLE 0 // $22 false +#endif - #ifndef DEFAULT_HOMING_DIR_MASK - #define DEFAULT_HOMING_DIR_MASK 3 // $23 move positive dir Z, negative X,Y - #endif +#ifndef DEFAULT_HOMING_DIR_MASK +# define DEFAULT_HOMING_DIR_MASK 3 // $23 move positive dir Z, negative X,Y +#endif - #ifndef DEFAULT_HOMING_FEED_RATE - #define DEFAULT_HOMING_FEED_RATE 200.0 // $24 mm/min - #endif +#ifndef DEFAULT_HOMING_FEED_RATE +# define DEFAULT_HOMING_FEED_RATE 200.0 // $24 mm/min +#endif - #ifndef DEFAULT_HOMING_SEEK_RATE - #define DEFAULT_HOMING_SEEK_RATE 2000.0 // $25 mm/min - #endif +#ifndef DEFAULT_HOMING_SEEK_RATE +# define DEFAULT_HOMING_SEEK_RATE 2000.0 // $25 mm/min +#endif - #ifndef DEFAULT_HOMING_DEBOUNCE_DELAY - #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // $26 msec (0-65k) - #endif +#ifndef DEFAULT_HOMING_DEBOUNCE_DELAY +# define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // $26 msec (0-65k) +#endif - #ifndef DEFAULT_HOMING_PULLOFF - #define DEFAULT_HOMING_PULLOFF 1.0 // $27 mm - #endif +#ifndef DEFAULT_HOMING_PULLOFF +# define DEFAULT_HOMING_PULLOFF 1.0 // $27 mm +#endif - // ======== SPINDLE STUFF ==================== - #ifndef SPINDLE_TYPE - #define SPINDLE_TYPE SPINDLE_TYPE_NONE - #endif +// ======== SPINDLE STUFF ==================== +#ifndef SPINDLE_TYPE +# define SPINDLE_TYPE SPINDLE_TYPE_NONE +#endif - #ifndef DEFAULT_SPINDLE_RPM_MIN // $31 - #define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm - #endif +#ifndef DEFAULT_SPINDLE_RPM_MIN // $31 +# define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm +#endif - #ifndef DEFAULT_LASER_MODE // $32 - #define DEFAULT_LASER_MODE 0 // false - #endif +#ifndef DEFAULT_LASER_MODE // $32 +# define DEFAULT_LASER_MODE 0 // false +#endif - #ifndef DEFAULT_SPINDLE_RPM_MAX // $30 - #define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm - #endif +#ifndef DEFAULT_SPINDLE_RPM_MAX // $30 +# define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm +#endif - #ifndef DEFAULT_SPINDLE_FREQ - #define DEFAULT_SPINDLE_FREQ 5000.0 // $33 Hz (extended set) - #endif +#ifndef DEFAULT_SPINDLE_FREQ +# define DEFAULT_SPINDLE_FREQ 5000.0 // $33 Hz (extended set) +#endif - #ifndef DEFAULT_SPINDLE_OFF_VALUE - #define DEFAULT_SPINDLE_OFF_VALUE 0.0 // $34 Percent of full period(extended set) - #endif +#ifndef DEFAULT_SPINDLE_OFF_VALUE +# define DEFAULT_SPINDLE_OFF_VALUE 0.0 // $34 Percent of full period(extended set) +#endif - #ifndef DEFAULT_SPINDLE_MIN_VALUE - #define DEFAULT_SPINDLE_MIN_VALUE 0.0 // $35 Percent of full period (extended set) - #endif +#ifndef DEFAULT_SPINDLE_MIN_VALUE +# define DEFAULT_SPINDLE_MIN_VALUE 0.0 // $35 Percent of full period (extended set) +#endif - #ifndef DEFAULT_SPINDLE_MAX_VALUE - #define DEFAULT_SPINDLE_MAX_VALUE 100.0 // $36 Percent of full period (extended set) - #endif +#ifndef DEFAULT_SPINDLE_MAX_VALUE +# define DEFAULT_SPINDLE_MAX_VALUE 100.0 // $36 Percent of full period (extended set) +#endif - #ifndef DEFAULT_SPINDLE_DELAY_SPINUP - #define DEFAULT_SPINDLE_DELAY_SPINUP 0 - #endif +#ifndef DEFAULT_SPINDLE_DELAY_SPINUP +# define DEFAULT_SPINDLE_DELAY_SPINUP 0 +#endif - #ifndef DEFAULT_SPINDLE_DELAY_SPINDOWN - #define DEFAULT_SPINDLE_DELAY_SPINDOWN 0 - #endif +#ifndef DEFAULT_SPINDLE_DELAY_SPINDOWN +# define DEFAULT_SPINDLE_DELAY_SPINDOWN 0 +#endif - // ================ user settings ===================== - #ifndef DEFAULT_USER_INT_80 - #define DEFAULT_USER_INT_80 0 // $80 User integer setting - #endif +// ================ user settings ===================== +#ifndef DEFAULT_USER_INT_80 +# define DEFAULT_USER_INT_80 0 // $80 User integer setting +#endif - #ifndef DEFAULT_USER_INT_81 - #define DEFAULT_USER_INT_81 0 // $81 User integer setting - #endif +#ifndef DEFAULT_USER_INT_81 +# define DEFAULT_USER_INT_81 0 // $81 User integer setting +#endif - #ifndef DEFAULT_USER_INT_82 - #define DEFAULT_USER_INT_82 0 // $82 User integer setting - #endif +#ifndef DEFAULT_USER_INT_82 +# define DEFAULT_USER_INT_82 0 // $82 User integer setting +#endif - #ifndef DEFAULT_USER_INT_83 - #define DEFAULT_USER_INT_83 0 // $83 User integer setting - #endif +#ifndef DEFAULT_USER_INT_83 +# define DEFAULT_USER_INT_83 0 // $83 User integer setting +#endif - #ifndef DEFAULT_USER_INT_84 - #define DEFAULT_USER_INT_84 0 // $84 User integer setting - #endif +#ifndef DEFAULT_USER_INT_84 +# define DEFAULT_USER_INT_84 0 // $84 User integer setting +#endif - #ifndef DEFAULT_USER_FLOAT_90 - #define DEFAULT_USER_FLOAT_90 0.0 // $90 User integer setting - #endif +#ifndef DEFAULT_USER_FLOAT_90 +# define DEFAULT_USER_FLOAT_90 0.0 // $90 User integer setting +#endif - #ifndef DEFAULT_USER_FLOAT_91 - #define DEFAULT_USER_FLOAT_91 0.0 // $92 User integer setting - #endif +#ifndef DEFAULT_USER_FLOAT_91 +# define DEFAULT_USER_FLOAT_91 0.0 // $92 User integer setting +#endif - #ifndef DEFAULT_USER_FLOAT_92 - #define DEFAULT_USER_FLOAT_92 0.0 // $92 User integer setting - #endif +#ifndef DEFAULT_USER_FLOAT_92 +# define DEFAULT_USER_FLOAT_92 0.0 // $92 User integer setting +#endif - #ifndef DEFAULT_USER_FLOAT_93 - #define DEFAULT_USER_FLOAT_93 0.0 // $93 User integer setting - #endif +#ifndef DEFAULT_USER_FLOAT_93 +# define DEFAULT_USER_FLOAT_93 0.0 // $93 User integer setting +#endif - #ifndef DEFAULT_USER_FLOAT_94 - #define DEFAULT_USER_FLOAT_94 0.0 // $94 User integer setting - #endif +#ifndef DEFAULT_USER_FLOAT_94 +# define DEFAULT_USER_FLOAT_94 0.0 // $94 User integer setting +#endif +// =========== AXIS RESOLUTION ====== - // =========== AXIS RESOLUTION ====== +#ifndef DEFAULT_X_STEPS_PER_MM +# define DEFAULT_X_STEPS_PER_MM 100.0 +#endif +#ifndef DEFAULT_Y_STEPS_PER_MM +# define DEFAULT_Y_STEPS_PER_MM 100.0 +#endif +#ifndef DEFAULT_Z_STEPS_PER_MM +# define DEFAULT_Z_STEPS_PER_MM 100.0 +#endif +#ifndef DEFAULT_A_STEPS_PER_MM +# define DEFAULT_A_STEPS_PER_MM 100.0 +#endif +#ifndef DEFAULT_B_STEPS_PER_MM +# define DEFAULT_B_STEPS_PER_MM 100.0 +#endif +#ifndef DEFAULT_C_STEPS_PER_MM +# define DEFAULT_C_STEPS_PER_MM 100.0 +#endif - #ifndef DEFAULT_X_STEPS_PER_MM - #define DEFAULT_X_STEPS_PER_MM 100.0 - #endif - #ifndef DEFAULT_Y_STEPS_PER_MM - #define DEFAULT_Y_STEPS_PER_MM 100.0 - #endif - #ifndef DEFAULT_Z_STEPS_PER_MM - #define DEFAULT_Z_STEPS_PER_MM 100.0 - #endif - #ifndef DEFAULT_A_STEPS_PER_MM - #define DEFAULT_A_STEPS_PER_MM 100.0 - #endif - #ifndef DEFAULT_B_STEPS_PER_MM - #define DEFAULT_B_STEPS_PER_MM 100.0 - #endif - #ifndef DEFAULT_C_STEPS_PER_MM - #define DEFAULT_C_STEPS_PER_MM 100.0 - #endif +// ============ AXIS MAX SPPED ========= - // ============ AXIS MAX SPPED ========= +#ifndef DEFAULT_X_MAX_RATE +# define DEFAULT_X_MAX_RATE 1000.0 // mm/min +#endif +#ifndef DEFAULT_Y_MAX_RATE +# define DEFAULT_Y_MAX_RATE 1000.0 // mm/min +#endif +#ifndef DEFAULT_Z_MAX_RATE +# define DEFAULT_Z_MAX_RATE 1000.0 // mm/min +#endif +#ifndef DEFAULT_A_MAX_RATE +# define DEFAULT_A_MAX_RATE 1000.0 // mm/min +#endif +#ifndef DEFAULT_B_MAX_RATE +# define DEFAULT_B_MAX_RATE 1000.0 // mm/min +#endif +#ifndef DEFAULT_C_MAX_RATE +# define DEFAULT_C_MAX_RATE 1000.0 // mm/min +#endif - #ifndef DEFAULT_X_MAX_RATE - #define DEFAULT_X_MAX_RATE 1000.0 // mm/min - #endif - #ifndef DEFAULT_Y_MAX_RATE - #define DEFAULT_Y_MAX_RATE 1000.0 // mm/min - #endif - #ifndef DEFAULT_Z_MAX_RATE - #define DEFAULT_Z_MAX_RATE 1000.0 // mm/min - #endif - #ifndef DEFAULT_A_MAX_RATE - #define DEFAULT_A_MAX_RATE 1000.0 // mm/min - #endif - #ifndef DEFAULT_B_MAX_RATE - #define DEFAULT_B_MAX_RATE 1000.0 // mm/min - #endif - #ifndef DEFAULT_C_MAX_RATE - #define DEFAULT_C_MAX_RATE 1000.0 // mm/min - #endif +// ============== Axis Acceleration ========= +#define SEC_PER_MIN_SQ (60.0 * 60.0) // Seconds Per Minute Squared, for acceleration conversion +// Default accelerations are expressed in mm/sec^2 +#ifndef DEFAULT_X_ACCELERATION +# define DEFAULT_X_ACCELERATION 200.0 +#endif +#ifndef DEFAULT_Y_ACCELERATION +# define DEFAULT_Y_ACCELERATION 200.0 +#endif +#ifndef DEFAULT_Z_ACCELERATION +# define DEFAULT_Z_ACCELERATION 200.0 +#endif +#ifndef DEFAULT_A_ACCELERATION +# define DEFAULT_A_ACCELERATION 200.0 +#endif +#ifndef DEFAULT_B_ACCELERATION +# define DEFAULT_B_ACCELERATION 200.0 +#endif +#ifndef DEFAULT_C_ACCELERATION +# define DEFAULT_C_ACCELERATION 200.0 +#endif - // ============== Axis Acceleration ========= - #define SEC_PER_MIN_SQ (60.0*60.0) // Seconds Per Minute Squared, for acceleration conversion - // Default accelerations are expressed in mm/sec^2 - #ifndef DEFAULT_X_ACCELERATION - #define DEFAULT_X_ACCELERATION 200.0 - #endif - #ifndef DEFAULT_Y_ACCELERATION - #define DEFAULT_Y_ACCELERATION 200.0 - #endif - #ifndef DEFAULT_Z_ACCELERATION - #define DEFAULT_Z_ACCELERATION 200.0 - #endif - #ifndef DEFAULT_A_ACCELERATION - #define DEFAULT_A_ACCELERATION 200.0 - #endif - #ifndef DEFAULT_B_ACCELERATION - #define DEFAULT_B_ACCELERATION 200.0 - #endif - #ifndef DEFAULT_C_ACCELERATION - #define DEFAULT_C_ACCELERATION 200.0 - #endif +// ========= AXIS MAX TRAVEL ============ - // ========= AXIS MAX TRAVEL ============ +#ifndef DEFAULT_X_MAX_TRAVEL +# define DEFAULT_X_MAX_TRAVEL 300.0 // $130 mm NOTE: Must be a positive value. +#endif +#ifndef DEFAULT_Y_MAX_TRAVEL +# define DEFAULT_Y_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value. +#endif +#ifndef DEFAULT_Z_MAX_TRAVEL +# define DEFAULT_Z_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value. +#endif +#ifndef DEFAULT_A_MAX_TRAVEL +# define DEFAULT_A_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value. +#endif +#ifndef DEFAULT_B_MAX_TRAVEL +# define DEFAULT_B_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value. +#endif +#ifndef DEFAULT_C_MAX_TRAVEL +# define DEFAULT_C_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value. +#endif - #ifndef DEFAULT_X_MAX_TRAVEL - #define DEFAULT_X_MAX_TRAVEL 300.0 // $130 mm NOTE: Must be a positive value. - #endif - #ifndef DEFAULT_Y_MAX_TRAVEL - #define DEFAULT_Y_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value. - #endif - #ifndef DEFAULT_Z_MAX_TRAVEL - #define DEFAULT_Z_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value. - #endif - #ifndef DEFAULT_A_MAX_TRAVEL - #define DEFAULT_A_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value. - #endif - #ifndef DEFAULT_B_MAX_TRAVEL - #define DEFAULT_B_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value. - #endif - #ifndef DEFAULT_C_MAX_TRAVEL - #define DEFAULT_C_MAX_TRAVEL 300.0 // mm NOTE: Must be a positive value. - #endif +// ========== Motor current (SPI Drivers ) ============= +#ifndef DEFAULT_X_CURRENT +# define DEFAULT_X_CURRENT 0.25 // $140 current in amps (extended set) +#endif +#ifndef DEFAULT_Y_CURRENT +# define DEFAULT_Y_CURRENT 0.25 // $141 current in amps (extended set) +#endif +#ifndef DEFAULT_Z_CURRENT +# define DEFAULT_Z_CURRENT 0.25 // $142 current in amps (extended set) +#endif +#ifndef DEFAULT_A_CURRENT +# define DEFAULT_A_CURRENT 0.25 // $143 current in amps (extended set) +#endif +#ifndef DEFAULT_B_CURRENT +# define DEFAULT_B_CURRENT 0.25 // $144 current in amps (extended set) +#endif +#ifndef DEFAULT_C_CURRENT +# define DEFAULT_C_CURRENT 0.25 // $145 current in amps (extended set) +#endif - // ========== Motor current (SPI Drivers ) ============= - #ifndef DEFAULT_X_CURRENT - #define DEFAULT_X_CURRENT 0.25 // $140 current in amps (extended set) - #endif - #ifndef DEFAULT_Y_CURRENT - #define DEFAULT_Y_CURRENT 0.25 // $141 current in amps (extended set) - #endif - #ifndef DEFAULT_Z_CURRENT - #define DEFAULT_Z_CURRENT 0.25 // $142 current in amps (extended set) - #endif - #ifndef DEFAULT_A_CURRENT - #define DEFAULT_A_CURRENT 0.25 // $143 current in amps (extended set) - #endif - #ifndef DEFAULT_B_CURRENT - #define DEFAULT_B_CURRENT 0.25 // $144 current in amps (extended set) - #endif - #ifndef DEFAULT_C_CURRENT - #define DEFAULT_C_CURRENT 0.25 // $145 current in amps (extended set) - #endif +// ========== Motor hold current (SPI Drivers ) ============= - // ========== Motor hold current (SPI Drivers ) ============= +#ifndef DEFAULT_X_HOLD_CURRENT +# define DEFAULT_X_HOLD_CURRENT 0.125 // $150 current in amps (extended set) +#endif +#ifndef DEFAULT_Y_HOLD_CURRENT +# define DEFAULT_Y_HOLD_CURRENT 0.125 // $151 current in amps (extended set) +#endif +#ifndef DEFAULT_Z_HOLD_CURRENT +# define DEFAULT_Z_HOLD_CURRENT 0.125 // $152 current in amps (extended set) +#endif +#ifndef DEFAULT_A_HOLD_CURRENT +# define DEFAULT_A_HOLD_CURRENT 0.125 // $153 current in amps (extended set) +#endif +#ifndef DEFAULT_B_HOLD_CURRENT +# define DEFAULT_B_HOLD_CURRENT 0.125 // $154 current in amps (extended set) +#endif +#ifndef DEFAULT_C_HOLD_CURRENT +# define DEFAULT_C_HOLD_CURRENT 0.125 // $154 current in amps (extended set) +#endif - #ifndef DEFAULT_X_HOLD_CURRENT - #define DEFAULT_X_HOLD_CURRENT 0.125 // $150 current in amps (extended set) - #endif - #ifndef DEFAULT_Y_HOLD_CURRENT - #define DEFAULT_Y_HOLD_CURRENT 0.125 // $151 current in amps (extended set) - #endif - #ifndef DEFAULT_Z_HOLD_CURRENT - #define DEFAULT_Z_HOLD_CURRENT 0.125 // $152 current in amps (extended set) - #endif - #ifndef DEFAULT_A_HOLD_CURRENT - #define DEFAULT_A_HOLD_CURRENT 0.125 // $153 current in amps (extended set) - #endif - #ifndef DEFAULT_B_HOLD_CURRENT - #define DEFAULT_B_HOLD_CURRENT 0.125 // $154 current in amps (extended set) - #endif - #ifndef DEFAULT_C_HOLD_CURRENT - #define DEFAULT_C_HOLD_CURRENT 0.125 // $154 current in amps (extended set) - #endif +// ========== Microsteps (SPI Drivers ) ================ - // ========== Microsteps (SPI Drivers ) ================ +#ifndef DEFAULT_X_MICROSTEPS +# define DEFAULT_X_MICROSTEPS 16 // $160 micro steps (extended set) +#endif +#ifndef DEFAULT_Y_MICROSTEPS +# define DEFAULT_Y_MICROSTEPS 16 // $161 micro steps (extended set) +#endif +#ifndef DEFAULT_Z_MICROSTEPS +# define DEFAULT_Z_MICROSTEPS 16 // $162 micro steps (extended set) +#endif +#ifndef DEFAULT_A_MICROSTEPS +# define DEFAULT_A_MICROSTEPS 16 // $163 micro steps (extended set) +#endif +#ifndef DEFAULT_B_MICROSTEPS +# define DEFAULT_B_MICROSTEPS 16 // $164 micro steps (extended set) +#endif +#ifndef DEFAULT_C_MICROSTEPS +# define DEFAULT_C_MICROSTEPS 16 // $165 micro steps (extended set) +#endif - #ifndef DEFAULT_X_MICROSTEPS - #define DEFAULT_X_MICROSTEPS 16 // $160 micro steps (extended set) - #endif - #ifndef DEFAULT_Y_MICROSTEPS - #define DEFAULT_Y_MICROSTEPS 16 // $161 micro steps (extended set) - #endif - #ifndef DEFAULT_Z_MICROSTEPS - #define DEFAULT_Z_MICROSTEPS 16 // $162 micro steps (extended set) - #endif - #ifndef DEFAULT_A_MICROSTEPS - #define DEFAULT_A_MICROSTEPS 16 // $163 micro steps (extended set) - #endif - #ifndef DEFAULT_B_MICROSTEPS - #define DEFAULT_B_MICROSTEPS 16 // $164 micro steps (extended set) - #endif - #ifndef DEFAULT_C_MICROSTEPS - #define DEFAULT_C_MICROSTEPS 16 // $165 micro steps (extended set) - #endif +// ========== Stallguard (SPI Drivers ) ================ - // ========== Stallguard (SPI Drivers ) ================ +#ifndef DEFAULT_X_STALLGUARD +# define DEFAULT_X_STALLGUARD 16 // $170 stallguard (extended set) +#endif +#ifndef DEFAULT_Y_STALLGUARD +# define DEFAULT_Y_STALLGUARD 16 // $171 stallguard (extended set) +#endif +#ifndef DEFAULT_Z_STALLGUARD +# define DEFAULT_Z_STALLGUARD 16 // $172 stallguard (extended set) +#endif +#ifndef DEFAULT_A_STALLGUARD +# define DEFAULT_A_STALLGUARD 16 // $173 stallguard (extended set) +#endif +#ifndef DEFAULT_B_STALLGUARD +# define DEFAULT_B_STALLGUARD 16 // $174 stallguard (extended set) +#endif +#ifndef DEFAULT_C_STALLGUARD +# define DEFAULT_C_STALLGUARD 16 // $175 stallguard (extended set) +#endif - #ifndef DEFAULT_X_STALLGUARD - #define DEFAULT_X_STALLGUARD 16 // $170 stallguard (extended set) - #endif - #ifndef DEFAULT_Y_STALLGUARD - #define DEFAULT_Y_STALLGUARD 16 // $171 stallguard (extended set) - #endif - #ifndef DEFAULT_Z_STALLGUARD - #define DEFAULT_Z_STALLGUARD 16 // $172 stallguard (extended set) - #endif - #ifndef DEFAULT_A_STALLGUARD - #define DEFAULT_A_STALLGUARD 16 // $173 stallguard (extended set) - #endif - #ifndef DEFAULT_B_STALLGUARD - #define DEFAULT_B_STALLGUARD 16 // $174 stallguard (extended set) - #endif - #ifndef DEFAULT_C_STALLGUARD - #define DEFAULT_C_STALLGUARD 16 // $175 stallguard (extended set) - #endif - - // ================== pin defaults ======================== - // Here is a place to default pins to UNDEFINED_PIN. // This can eliminate checking to see if the pin is defined because // the overridden pinMode and digitalWrite functions will deal with it. #ifndef STEPPERS_DISABLE_PIN - #define STEPPERS_DISABLE_PIN UNDEFINED_PIN +# define STEPPERS_DISABLE_PIN UNDEFINED_PIN #endif #ifndef X_DISABLE_PIN - #define X_DISABLE_PIN UNDEFINED_PIN +# define X_DISABLE_PIN UNDEFINED_PIN #endif #ifndef Y_DISABLE_PIN - #define Y_DISABLE_PIN UNDEFINED_PIN +# define Y_DISABLE_PIN UNDEFINED_PIN #endif #ifndef Z_DISABLE_PIN - #define Z_DISABLE_PIN UNDEFINED_PIN +# define Z_DISABLE_PIN UNDEFINED_PIN #endif #ifndef A_DISABLE_PIN - #define A_DISABLE_PIN UNDEFINED_PIN +# define A_DISABLE_PIN UNDEFINED_PIN #endif #ifndef B_DISABLE_PIN - #define B_DISABLE_PIN UNDEFINED_PIN +# define B_DISABLE_PIN UNDEFINED_PIN #endif #ifndef C_DISABLE_PIN - #define C_DISABLE_PIN UNDEFINED_PIN +# define C_DISABLE_PIN UNDEFINED_PIN #endif #ifndef X2_DISABLE_PIN - #define X2_DISABLE_PIN UNDEFINED_PIN +# define X2_DISABLE_PIN UNDEFINED_PIN #endif #ifndef Y2_DISABLE_PIN - #define Y2_DISABLE_PIN UNDEFINED_PIN +# define Y2_DISABLE_PIN UNDEFINED_PIN #endif #ifndef Z2_DISABLE_PIN - #define Z2_DISABLE_PIN UNDEFINED_PIN +# define Z2_DISABLE_PIN UNDEFINED_PIN #endif #ifndef A2_DISABLE_PIN - #define A2_DISABLE_PIN UNDEFINED_PIN +# define A2_DISABLE_PIN UNDEFINED_PIN #endif #ifndef B2_DISABLE_PIN - #define B2_DISABLE_PIN UNDEFINED_PIN +# define B2_DISABLE_PIN UNDEFINED_PIN #endif #ifndef C2_DISABLE_PIN - #define C2_DISABLE_PIN UNDEFINED_PIN +# define C2_DISABLE_PIN UNDEFINED_PIN #endif #ifndef X_LIMIT_PIN - #define X_LIMIT_PIN UNDEFINED_PIN +# define X_LIMIT_PIN UNDEFINED_PIN #endif #ifndef Y_LIMIT_PIN - #define Y_LIMIT_PIN UNDEFINED_PIN +# define Y_LIMIT_PIN UNDEFINED_PIN #endif #ifndef Z_LIMIT_PIN - #define Z_LIMIT_PIN UNDEFINED_PIN +# define Z_LIMIT_PIN UNDEFINED_PIN #endif #ifndef A_LIMIT_PIN - #define A_LIMIT_PIN UNDEFINED_PIN +# define A_LIMIT_PIN UNDEFINED_PIN #endif #ifndef B_LIMIT_PIN - #define B_LIMIT_PIN UNDEFINED_PIN +# define B_LIMIT_PIN UNDEFINED_PIN #endif #ifndef C_LIMIT_PIN - #define C_LIMIT_PIN UNDEFINED_PIN +# define C_LIMIT_PIN UNDEFINED_PIN #endif diff --git a/Grbl_Esp32/espresponse.cpp b/Grbl_Esp32/espresponse.cpp index 96da1c4a..fe2d5ae6 100644 --- a/Grbl_Esp32/espresponse.cpp +++ b/Grbl_Esp32/espresponse.cpp @@ -19,40 +19,42 @@ */ #include "grbl.h" #include "espresponse.h" -#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI) - #include "web_server.h" - #include +#if defined(ENABLE_HTTP) && defined(ENABLE_WIFI) +# include "web_server.h" +# include #endif -#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI) +#if defined(ENABLE_HTTP) && defined(ENABLE_WIFI) ESPResponseStream::ESPResponseStream(WebServer* webserver) { _header_sent = false; - _webserver = webserver; - _client = CLIENT_WEBUI; + _webserver = webserver; + _client = CLIENT_WEBUI; } #endif ESPResponseStream::ESPResponseStream() { _client = CLIENT_INPUT; -#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI) +#if defined(ENABLE_HTTP) && defined(ENABLE_WIFI) _header_sent = false; - _webserver = NULL; + _webserver = NULL; #endif } ESPResponseStream::ESPResponseStream(uint8_t client, bool byid) { - (void)byid; //fake parameter to avoid confusion with pointer one (NULL == 0) + (void)byid; //fake parameter to avoid confusion with pointer one (NULL == 0) _client = client; -#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI) +#if defined(ENABLE_HTTP) && defined(ENABLE_WIFI) _header_sent = false; - _webserver = NULL; + _webserver = NULL; #endif } void ESPResponseStream::println(const char* data) { print(data); - if (_client == CLIENT_TELNET) print("\r\n"); - else print("\n"); + if (_client == CLIENT_TELNET) + print("\r\n"); + else + print("\n"); } //helper to format size to readable string @@ -68,8 +70,9 @@ String ESPResponseStream::formatBytes(uint64_t bytes) { } void ESPResponseStream::print(const char* data) { - if (_client == CLIENT_INPUT) return; -#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI) + if (_client == CLIENT_INPUT) + return; +#if defined(ENABLE_HTTP) && defined(ENABLE_WIFI) if (_webserver) { if (!_header_sent) { _webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); @@ -88,21 +91,23 @@ void ESPResponseStream::print(const char* data) { return; } #endif - if (_client == CLIENT_WEBUI) return; //this is sanity check + if (_client == CLIENT_WEBUI) + return; //this is sanity check grbl_send(_client, data); } void ESPResponseStream::flush() { -#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI) +#if defined(ENABLE_HTTP) && defined(ENABLE_WIFI) if (_webserver) { if (_header_sent) { //send data - if (_buffer.length() > 0)_webserver->sendContent(_buffer); + if (_buffer.length() > 0) + _webserver->sendContent(_buffer); //close connection _webserver->sendContent(""); } _header_sent = false; - _buffer = ""; + _buffer = ""; } #endif } diff --git a/Grbl_Esp32/espresponse.h b/Grbl_Esp32/espresponse.h index 100c3c7a..e20605e1 100644 --- a/Grbl_Esp32/espresponse.h +++ b/Grbl_Esp32/espresponse.h @@ -20,28 +20,29 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI) - class WebServer; +#if defined(ENABLE_HTTP) && defined(ENABLE_WIFI) +class WebServer; #endif class ESPResponseStream { - public: - void print(const char* data); - void println(const char* data); - void flush(); - bool anyOutput() { return _header_sent; } +public: + void print(const char* data); + void println(const char* data); + void flush(); + bool anyOutput() { return _header_sent; } static String formatBytes(uint64_t bytes); - uint8_t client() {return _client;} -#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI) + uint8_t client() { return _client; } +#if defined(ENABLE_HTTP) && defined(ENABLE_WIFI) ESPResponseStream(WebServer* webserver); #endif ESPResponseStream(uint8_t client, bool byid = true); ESPResponseStream(); - private: + +private: uint8_t _client; - bool _header_sent; -#if defined (ENABLE_HTTP) && defined(ENABLE_WIFI) + bool _header_sent; +#if defined(ENABLE_HTTP) && defined(ENABLE_WIFI) WebServer* _webserver; - String _buffer; + String _buffer; #endif }; diff --git a/Grbl_Esp32/gcode.cpp b/Grbl_Esp32/gcode.cpp index 0fd5eb75..879f1715 100644 --- a/Grbl_Esp32/gcode.cpp +++ b/Grbl_Esp32/gcode.cpp @@ -28,19 +28,18 @@ // arbitrary value, and some GUIs may require more. So we increased it based on a max safe // value when converting a float (7.2 digit precision)s to an integer. #define MAX_LINE_NUMBER 10000000 -#define MAX_TOOL_NUMBER 255 // Limited by max unsigned 8-bit value +#define MAX_TOOL_NUMBER 255 // Limited by max unsigned 8-bit value #define AXIS_COMMAND_NONE 0 #define AXIS_COMMAND_NON_MODAL 1 #define AXIS_COMMAND_MOTION_MODE 2 -#define AXIS_COMMAND_TOOL_LENGTH_OFFSET 3 // *Undefined but required +#define AXIS_COMMAND_TOOL_LENGTH_OFFSET 3 // *Undefined but required // Declare gc extern struct parser_state_t gc_state; parser_block_t gc_block; -#define FAIL(status) return(status); - +#define FAIL(status) return (status); void gc_init() { memset(&gc_state, 0, sizeof(parser_state_t)); @@ -49,23 +48,21 @@ void gc_init() { report_status_message(STATUS_SETTING_READ_FAIL, CLIENT_SERIAL); } - // Sets g-code parser position in mm. Input in steps. Called by the system abort and hard // limit pull-off routines. void gc_sync_position() { system_convert_array_steps_to_mpos(gc_state.position, sys_position); } - // Edit GCode line in-place, removing whitespace and comments and // converting to uppercase -void collapseGCode(char *line) { +void collapseGCode(char* line) { // parenPtr, if non-NULL, is the address of the character after ( char* parenPtr = NULL; // outPtr is the address where newly-processed characters will be placed. // outPtr is alway less than or equal to inPtr. char* outPtr = line; - char c; + char c; for (char* inPtr = line; (c = *inPtr) != '\0'; inPtr++) { if (isspace(c)) { continue; @@ -104,7 +101,7 @@ void collapseGCode(char *line) { break; default: if (!parenPtr) { - *outPtr++ = toupper(c); // make upper case + *outPtr++ = toupper(c); // make upper case } } } @@ -135,26 +132,26 @@ uint8_t gc_execute_line(char* line, uint8_t client) { executed after successful error-checking. The parser block struct also contains a block values struct, word tracking variables, and a non-modal commands tracker for the new block. This struct contains all of the necessary information to execute the block. */ - memset(&gc_block, 0, sizeof(parser_block_t)); // Initialize the parser block struct. - memcpy(&gc_block.modal, &gc_state.modal, sizeof(gc_modal_t)); // Copy current modes + memset(&gc_block, 0, sizeof(parser_block_t)); // Initialize the parser block struct. + memcpy(&gc_block.modal, &gc_state.modal, sizeof(gc_modal_t)); // Copy current modes uint8_t axis_command = AXIS_COMMAND_NONE; uint8_t axis_0, axis_1, axis_linear; - uint8_t coord_select = 0; // Tracks G10 P coordinate selection for execution + uint8_t coord_select = 0; // Tracks G10 P coordinate selection for execution // Initialize bitflag tracking variables for axis indices compatible operations. - uint8_t axis_words = 0; // XYZ tracking - uint8_t ijk_words = 0; // IJK tracking + uint8_t axis_words = 0; // XYZ tracking + uint8_t ijk_words = 0; // IJK tracking // Initialize command and value words and parser flags variables. - uint16_t command_words = 0; // Tracks G and M command words. Also used for modal group violations. - uint16_t value_words = 0; // Tracks value words. - uint8_t gc_parser_flags = GC_PARSER_NONE; + uint16_t command_words = 0; // Tracks G and M command words. Also used for modal group violations. + uint16_t value_words = 0; // Tracks value words. + uint8_t gc_parser_flags = GC_PARSER_NONE; // Determine if the line is a jogging motion or a normal g-code block. - if (line[0] == '$') { // NOTE: `$J=` already parsed when passed to this function. + if (line[0] == '$') { // NOTE: `$J=` already parsed when passed to this function. // Set G1 and G94 enforced modes to ensure accurate error checks. gc_parser_flags |= GC_PARSER_JOG_MOTION; - gc_block.modal.motion = MOTION_MODE_LINEAR; + gc_block.modal.motion = MOTION_MODE_LINEAR; gc_block.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN; #ifdef USE_LINE_NUMBERS - gc_block.values.n = JOG_LINE_NUMBER; // Initialize default line number reported during jog. + gc_block.values.n = JOG_LINE_NUMBER; // Initialize default line number reported during jog. #endif } /* ------------------------------------------------------------------------------------- @@ -162,25 +159,25 @@ uint8_t gc_execute_line(char* line, uint8_t client) { a number, which can either be a 'G'/'M' command or sets/assigns a command value. Also, perform initial error-checks for command word modal group violations, for any repeated words, and for negative values set for the value words F, N, P, T, and S. */ - uint8_t word_bit = 0; // Bit-value for assigning tracking variables - uint8_t char_counter; - char letter; - float value; - uint8_t int_value = 0; - uint16_t mantissa = 0; + uint8_t word_bit = 0; // Bit-value for assigning tracking variables + uint8_t char_counter; + char letter; + float value; + uint8_t int_value = 0; + uint16_t mantissa = 0; if (gc_parser_flags & GC_PARSER_JOG_MOTION) { - char_counter = 3; // Start parsing after `$J=` + char_counter = 3; // Start parsing after `$J=` } else char_counter = 0; - while (line[char_counter] != 0) { // Loop until no more g-code words in line. + while (line[char_counter] != 0) { // Loop until no more g-code words in line. // Import the next g-code word, expecting a letter followed by a value. Otherwise, error out. letter = line[char_counter]; if ((letter < 'A') || (letter > 'Z')) { - FAIL(STATUS_EXPECTED_COMMAND_LETTER); // [Expected word letter] + FAIL(STATUS_EXPECTED_COMMAND_LETTER); // [Expected word letter] } char_counter++; if (!read_float(line, &char_counter, &value)) { - FAIL(STATUS_BAD_NUMBER_FORMAT); // [Expected word value] + FAIL(STATUS_BAD_NUMBER_FORMAT); // [Expected word value] } // Convert values to smaller uint8 significand and mantissa values for parsing this word. // NOTE: Mantissa is multiplied by 100 to catch non-integer command values. This is more @@ -190,357 +187,335 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // we would simply need to change the mantissa to int16, but this add compiled flash space. // Maybe update this later. int_value = trunc(value); - mantissa = round(100 * (value - int_value)); // Compute mantissa for Gxx.x commands. + mantissa = round(100 * (value - int_value)); // Compute mantissa for Gxx.x commands. // NOTE: Rounding must be used to catch small floating point errors. // Check if the g-code word is supported or errors due to modal group violations or has // been repeated in the g-code block. If ok, update the command or record its value. switch (letter) { - /* 'G' and 'M' Command Words: Parse commands and check for modal group violations. + /* 'G' and 'M' Command Words: Parse commands and check for modal group violations. NOTE: Modal group numbers are defined in Table 4 of NIST RS274-NGC v3, pg.20 */ - case 'G': - // Determine 'G' command and its modal group - switch (int_value) { - case 10: - case 28: - case 30: - case 92: - // Check for G10/28/30/92 being called with G0/1/2/3/38 on same block. - // * G43.1 is also an axis command but is not explicitly defined this way. - if (mantissa == 0) { // Ignore G28.1, G30.1, and G92.1 - if (axis_command) { - FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); // [Axis word/command conflict] - } - axis_command = AXIS_COMMAND_NON_MODAL; - } - // No break. Continues to next line. - case 4: - case 53: - word_bit = MODAL_GROUP_G0; - gc_block.non_modal_command = int_value; - if ((int_value == 28) || (int_value == 30) || (int_value == 92)) { - if (!((mantissa == 0) || (mantissa == 10))) - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); - gc_block.non_modal_command += mantissa; - mantissa = 0; // Set to zero to indicate valid non-integer G command. - } - break; - case 0: - case 1: - case 2: - case 3: - case 38: -#ifndef PROBE_PIN //only allow G38 "Probe" commands if a probe pin is defined. - if (int_value == 38) { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "No probe pin defined"); - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G command] - } + case 'G': + // Determine 'G' command and its modal group + switch (int_value) { + case 10: + case 28: + case 30: + case 92: + // Check for G10/28/30/92 being called with G0/1/2/3/38 on same block. + // * G43.1 is also an axis command but is not explicitly defined this way. + if (mantissa == 0) { // Ignore G28.1, G30.1, and G92.1 + if (axis_command) { + FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); // [Axis word/command conflict] + } + axis_command = AXIS_COMMAND_NON_MODAL; + } + // No break. Continues to next line. + case 4: + case 53: + word_bit = MODAL_GROUP_G0; + gc_block.non_modal_command = int_value; + if ((int_value == 28) || (int_value == 30) || (int_value == 92)) { + if (!((mantissa == 0) || (mantissa == 10))) + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); + gc_block.non_modal_command += mantissa; + mantissa = 0; // Set to zero to indicate valid non-integer G command. + } + break; + case 0: + case 1: + case 2: + case 3: + case 38: +#ifndef PROBE_PIN //only allow G38 "Probe" commands if a probe pin is defined. + if (int_value == 38) { + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "No probe pin defined"); + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G command] + } #endif - // Check for G0/1/2/3/38 being called with G10/28/30/92 on same block. - // * G43.1 is also an axis command but is not explicitly defined this way. - if (axis_command) { - FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); // [Axis word/command conflict] + // Check for G0/1/2/3/38 being called with G10/28/30/92 on same block. + // * G43.1 is also an axis command but is not explicitly defined this way. + if (axis_command) { + FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); // [Axis word/command conflict] + } + axis_command = AXIS_COMMAND_MOTION_MODE; + // No break. Continues to next line. + case 80: + word_bit = MODAL_GROUP_G1; + gc_block.modal.motion = int_value; + if (int_value == 38) { + if (!((mantissa == 20) || (mantissa == 30) || (mantissa == 40) || (mantissa == 50))) { + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G38.x command] + } + gc_block.modal.motion += (mantissa / 10) + 100; + mantissa = 0; // Set to zero to indicate valid non-integer G command. + } + break; + case 17: + case 18: + case 19: + word_bit = MODAL_GROUP_G2; + gc_block.modal.plane_select = int_value - 17; + break; + case 90: + case 91: + if (mantissa == 0) { + word_bit = MODAL_GROUP_G3; + gc_block.modal.distance = int_value - 90; + } else { + word_bit = MODAL_GROUP_G4; + if ((mantissa != 10) || (int_value == 90)) { + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [G90.1 not supported] + } + mantissa = 0; // Set to zero to indicate valid non-integer G command. + // Otherwise, arc IJK incremental mode is default. G91.1 does nothing. + } + break; + case 93: + case 94: + word_bit = MODAL_GROUP_G5; + gc_block.modal.feed_rate = 94 - int_value; + break; + case 20: + case 21: + word_bit = MODAL_GROUP_G6; + gc_block.modal.units = 21 - int_value; + break; + case 40: + word_bit = MODAL_GROUP_G7; + // NOTE: Not required since cutter radius compensation is always disabled. Only here + // to support G40 commands that often appear in g-code program headers to setup defaults. + // gc_block.modal.cutter_comp = CUTTER_COMP_DISABLE; // G40 + break; + case 43: + case 49: + word_bit = MODAL_GROUP_G8; + // NOTE: The NIST g-code standard vaguely states that when a tool length offset is changed, + // there cannot be any axis motion or coordinate offsets updated. Meaning G43, G43.1, and G49 + // all are explicit axis commands, regardless if they require axis words or not. + if (axis_command) + FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); + // [Axis word/command conflict] } + axis_command = AXIS_COMMAND_TOOL_LENGTH_OFFSET; + if (int_value == 49) // G49 + gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_CANCEL; + else if (mantissa == 10) // G43.1 + gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC; + else { + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G43.x command] + } + mantissa = 0; // Set to zero to indicate valid non-integer G command. + break; + case 54: + case 55: + case 56: + case 57: + case 58: + case 59: + // NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.) + word_bit = MODAL_GROUP_G12; + gc_block.modal.coord_select = int_value - 54; // Shift to array indexing. + break; + case 61: + word_bit = MODAL_GROUP_G13; + if (mantissa != 0) { + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [G61.1 not supported] + } + // gc_block.modal.control = CONTROL_MODE_EXACT_PATH; // G61 + break; + default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G command] } - axis_command = AXIS_COMMAND_MOTION_MODE; - // No break. Continues to next line. - case 80: - word_bit = MODAL_GROUP_G1; - gc_block.modal.motion = int_value; - if (int_value == 38) { - if (!((mantissa == 20) || (mantissa == 30) || (mantissa == 40) || (mantissa == 50))) { - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G38.x command] - } - gc_block.modal.motion += (mantissa / 10) + 100; - mantissa = 0; // Set to zero to indicate valid non-integer G command. + if (mantissa > 0) { + FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); // [Unsupported or invalid Gxx.x command] } + // Check for more than one command per modal group violations in the current block + // NOTE: Variable 'word_bit' is always assigned, if the command is valid. + if (bit_istrue(command_words, bit(word_bit))) + FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); + command_words |= bit(word_bit); break; - case 17: - case 18: - case 19: - word_bit = MODAL_GROUP_G2; - gc_block.modal.plane_select = int_value - 17; - break; - case 90: - case 91: - if (mantissa == 0) { - word_bit = MODAL_GROUP_G3; - gc_block.modal.distance = int_value - 90; - } else { - word_bit = MODAL_GROUP_G4; - if ((mantissa != 10) || (int_value == 90)) { - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [G90.1 not supported] - } - mantissa = 0; // Set to zero to indicate valid non-integer G command. - // Otherwise, arc IJK incremental mode is default. G91.1 does nothing. + case 'M': + // Determine 'M' command and its modal group + if (mantissa > 0) { + FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); // [No Mxx.x commands] } - break; - case 93: - case 94: - word_bit = MODAL_GROUP_G5; - gc_block.modal.feed_rate = 94 - int_value; - break; - case 20: - case 21: - word_bit = MODAL_GROUP_G6; - gc_block.modal.units = 21 - int_value; - break; - case 40: - word_bit = MODAL_GROUP_G7; - // NOTE: Not required since cutter radius compensation is always disabled. Only here - // to support G40 commands that often appear in g-code program headers to setup defaults. - // gc_block.modal.cutter_comp = CUTTER_COMP_DISABLE; // G40 - break; - case 43: - case 49: - word_bit = MODAL_GROUP_G8; - // NOTE: The NIST g-code standard vaguely states that when a tool length offset is changed, - // there cannot be any axis motion or coordinate offsets updated. Meaning G43, G43.1, and G49 - // all are explicit axis commands, regardless if they require axis words or not. - if (axis_command) - FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); - // [Axis word/command conflict] } - axis_command = AXIS_COMMAND_TOOL_LENGTH_OFFSET; - if (int_value == 49) // G49 - gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_CANCEL; - else if (mantissa == 10) // G43.1 - gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC; - else { - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G43.x command] - } - mantissa = 0; // Set to zero to indicate valid non-integer G command. - break; - case 54: - case 55: - case 56: - case 57: - case 58: - case 59: - // NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.) - word_bit = MODAL_GROUP_G12; - gc_block.modal.coord_select = int_value - 54; // Shift to array indexing. - break; - case 61: - word_bit = MODAL_GROUP_G13; - if (mantissa != 0) { - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [G61.1 not supported] - } - // gc_block.modal.control = CONTROL_MODE_EXACT_PATH; // G61 - break; - default: - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G command] - } - if (mantissa > 0) { - FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); // [Unsupported or invalid Gxx.x command] - } - // Check for more than one command per modal group violations in the current block - // NOTE: Variable 'word_bit' is always assigned, if the command is valid. - if (bit_istrue(command_words, bit(word_bit))) - FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); - command_words |= bit(word_bit); - break; - case 'M': - // Determine 'M' command and its modal group - if (mantissa > 0) { - FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); // [No Mxx.x commands] - } - switch (int_value) { - case 0: - case 1: - case 2: - case 30: - word_bit = MODAL_GROUP_M4; switch (int_value) { - case 0: - gc_block.modal.program_flow = PROGRAM_FLOW_PAUSED; - break; // Program pause - case 1: - break; // Optional stop not supported. Ignore. - default: - gc_block.modal.program_flow = int_value; // Program end and reset - } - break; - case 3: - case 4: - case 5: - word_bit = MODAL_GROUP_M7; - switch (int_value) { - case 3: - gc_block.modal.spindle = SPINDLE_ENABLE_CW; - break; - case 4: // Supported if SPINDLE_DIR_PIN is defined or laser mode is on. - if (spindle->is_reversable || laser_mode->get()) - gc_block.modal.spindle = SPINDLE_ENABLE_CCW; - else - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); - break; - case 5: - gc_block.modal.spindle = SPINDLE_DISABLE; - break; - } - break; - case 6: // tool change - word_bit = MODAL_GROUP_M6; - gc_block.modal.tool_change = TOOL_CHANGE; + case 0: + case 1: + case 2: + case 30: + word_bit = MODAL_GROUP_M4; + switch (int_value) { + case 0: gc_block.modal.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause + case 1: break; // Optional stop not supported. Ignore. + default: gc_block.modal.program_flow = int_value; // Program end and reset + } + break; + case 3: + case 4: + case 5: + word_bit = MODAL_GROUP_M7; + switch (int_value) { + case 3: gc_block.modal.spindle = SPINDLE_ENABLE_CW; break; + case 4: // Supported if SPINDLE_DIR_PIN is defined or laser mode is on. + if (spindle->is_reversable || laser_mode->get()) + gc_block.modal.spindle = SPINDLE_ENABLE_CCW; + else + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); + break; + case 5: gc_block.modal.spindle = SPINDLE_DISABLE; break; + } + break; + case 6: // tool change + word_bit = MODAL_GROUP_M6; + gc_block.modal.tool_change = TOOL_CHANGE; #ifdef USE_TOOL_CHANGE - //user_tool_change(gc_state.tool); + //user_tool_change(gc_state.tool); #endif - break; - case 7: - case 8: - case 9: - word_bit = MODAL_GROUP_M8; - switch (int_value) { + break; + case 7: + case 8: + case 9: + word_bit = MODAL_GROUP_M8; + switch (int_value) { #ifdef COOLANT_MIST_PIN - case 7: - gc_block.modal.coolant = COOLANT_MIST_ENABLE; - break; + case 7: gc_block.modal.coolant = COOLANT_MIST_ENABLE; break; #endif #ifdef COOLANT_FLOOD_PIN - case 8: - gc_block.modal.coolant = COOLANT_FLOOD_ENABLE; - break; + case 8: gc_block.modal.coolant = COOLANT_FLOOD_ENABLE; break; #endif - case 9: - gc_block.modal.coolant = COOLANT_DISABLE; - break; - } - break; + case 9: gc_block.modal.coolant = COOLANT_DISABLE; break; + } + break; #ifdef ENABLE_PARKING_OVERRIDE_CONTROL - case 56: - word_bit = MODAL_GROUP_M9; - gc_block.modal.override = OVERRIDE_PARKING_MOTION; - break; + case 56: + word_bit = MODAL_GROUP_M9; + gc_block.modal.override = OVERRIDE_PARKING_MOTION; + break; #endif - case 62: - case 63: - //grbl_sendf(CLIENT_SERIAL,"M%d...\r\n", int_value); - word_bit = MODAL_GROUP_M10; - switch (int_value) { - case 62: - gc_block.modal.io_control = NON_MODAL_IO_ENABLE; - break; - case 63: - gc_block.modal.io_control = NON_MODAL_IO_DISABLE; - break; - default: - break; + case 62: + case 63: + //grbl_sendf(CLIENT_SERIAL,"M%d...\r\n", int_value); + word_bit = MODAL_GROUP_M10; + switch (int_value) { + case 62: gc_block.modal.io_control = NON_MODAL_IO_ENABLE; break; + case 63: gc_block.modal.io_control = NON_MODAL_IO_DISABLE; break; + default: break; + } + break; + default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported M command] } + // Check for more than one command per modal group violations in the current block + // NOTE: Variable 'word_bit' is always assigned, if the command is valid. + if (bit_istrue(command_words, bit(word_bit))) + FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); + command_words |= bit(word_bit); break; + // NOTE: All remaining letters assign values. default: - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported M command] - } - // Check for more than one command per modal group violations in the current block - // NOTE: Variable 'word_bit' is always assigned, if the command is valid. - if (bit_istrue(command_words, bit(word_bit))) - FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); - command_words |= bit(word_bit); - break; - // NOTE: All remaining letters assign values. - default: - /* Non-Command Words: This initial parsing phase only checks for repeats of the remaining + /* Non-Command Words: This initial parsing phase only checks for repeats of the remaining legal g-code words and stores their value. Error-checking is performed later since some words (I,J,K,L,P,R) have multiple connotations and/or depend on the issued commands. */ - switch (letter) { + switch (letter) { #if (N_AXIS > A_AXIS) - case 'A': - word_bit = WORD_A; - gc_block.values.xyz[A_AXIS] = value; - axis_words |= bit(A_AXIS); - break; + case 'A': + word_bit = WORD_A; + gc_block.values.xyz[A_AXIS] = value; + axis_words |= bit(A_AXIS); + break; #endif #if (N_AXIS > B_AXIS) - case 'B': - word_bit = WORD_B; - gc_block.values.xyz[B_AXIS] = value; - axis_words |= bit(B_AXIS); - break; + case 'B': + word_bit = WORD_B; + gc_block.values.xyz[B_AXIS] = value; + axis_words |= bit(B_AXIS); + break; #endif #if (N_AXIS > C_AXIS) - case 'C': - word_bit = WORD_C; - gc_block.values.xyz[C_AXIS] = value; - axis_words |= bit(C_AXIS); - break; + case 'C': + word_bit = WORD_C; + gc_block.values.xyz[C_AXIS] = value; + axis_words |= bit(C_AXIS); + break; #endif - // case 'D': // Not supported - case 'F': - word_bit = WORD_F; - gc_block.values.f = value; - break; - // case 'H': // Not supported - case 'I': - word_bit = WORD_I; - gc_block.values.ijk[X_AXIS] = value; - ijk_words |= bit(X_AXIS); - break; - case 'J': - word_bit = WORD_J; - gc_block.values.ijk[Y_AXIS] = value; - ijk_words |= bit(Y_AXIS); - break; - case 'K': - word_bit = WORD_K; - gc_block.values.ijk[Z_AXIS] = value; - ijk_words |= bit(Z_AXIS); - break; - case 'L': - word_bit = WORD_L; - gc_block.values.l = int_value; - break; - case 'N': - word_bit = WORD_N; - gc_block.values.n = trunc(value); - break; - case 'P': - word_bit = WORD_P; - gc_block.values.p = value; - break; - // NOTE: For certain commands, P value must be an integer, but none of these commands are supported. - // case 'Q': // Not supported - case 'R': - word_bit = WORD_R; - gc_block.values.r = value; - break; - case 'S': - word_bit = WORD_S; - gc_block.values.s = value; - break; - case 'T': - word_bit = WORD_T; - if (value > MAX_TOOL_NUMBER) - FAIL(STATUS_GCODE_MAX_VALUE_EXCEEDED); - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Tool No: %d", int_value); - gc_state.tool = int_value; - break; - case 'X': - word_bit = WORD_X; - gc_block.values.xyz[X_AXIS] = value; - axis_words |= bit(X_AXIS); - break; - case 'Y': - word_bit = WORD_Y; - gc_block.values.xyz[Y_AXIS] = value; - axis_words |= bit(Y_AXIS); - break; - case 'Z': - word_bit = WORD_Z; - gc_block.values.xyz[Z_AXIS] = value; - axis_words |= bit(Z_AXIS); - break; - default: - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); - } - // NOTE: Variable 'word_bit' is always assigned, if the non-command letter is valid. - if (bit_istrue(value_words, bit(word_bit))) { - FAIL(STATUS_GCODE_WORD_REPEATED); // [Word repeated] - } - // Check for invalid negative values for words F, N, P, T, and S. - // NOTE: Negative value check is done here simply for code-efficiency. - if (bit(word_bit) & (bit(WORD_F) | bit(WORD_N) | bit(WORD_P) | bit(WORD_T) | bit(WORD_S))) { - if (value < 0.0) { - FAIL(STATUS_NEGATIVE_VALUE); // [Word value cannot be negative] + // case 'D': // Not supported + case 'F': + word_bit = WORD_F; + gc_block.values.f = value; + break; + // case 'H': // Not supported + case 'I': + word_bit = WORD_I; + gc_block.values.ijk[X_AXIS] = value; + ijk_words |= bit(X_AXIS); + break; + case 'J': + word_bit = WORD_J; + gc_block.values.ijk[Y_AXIS] = value; + ijk_words |= bit(Y_AXIS); + break; + case 'K': + word_bit = WORD_K; + gc_block.values.ijk[Z_AXIS] = value; + ijk_words |= bit(Z_AXIS); + break; + case 'L': + word_bit = WORD_L; + gc_block.values.l = int_value; + break; + case 'N': + word_bit = WORD_N; + gc_block.values.n = trunc(value); + break; + case 'P': + word_bit = WORD_P; + gc_block.values.p = value; + break; + // NOTE: For certain commands, P value must be an integer, but none of these commands are supported. + // case 'Q': // Not supported + case 'R': + word_bit = WORD_R; + gc_block.values.r = value; + break; + case 'S': + word_bit = WORD_S; + gc_block.values.s = value; + break; + case 'T': + word_bit = WORD_T; + if (value > MAX_TOOL_NUMBER) + FAIL(STATUS_GCODE_MAX_VALUE_EXCEEDED); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Tool No: %d", int_value); + gc_state.tool = int_value; + break; + case 'X': + word_bit = WORD_X; + gc_block.values.xyz[X_AXIS] = value; + axis_words |= bit(X_AXIS); + break; + case 'Y': + word_bit = WORD_Y; + gc_block.values.xyz[Y_AXIS] = value; + axis_words |= bit(Y_AXIS); + break; + case 'Z': + word_bit = WORD_Z; + gc_block.values.xyz[Z_AXIS] = value; + axis_words |= bit(Z_AXIS); + break; + default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } - } - value_words |= bit(word_bit); // Flag to indicate parameter assigned. + // NOTE: Variable 'word_bit' is always assigned, if the non-command letter is valid. + if (bit_istrue(value_words, bit(word_bit))) { + FAIL(STATUS_GCODE_WORD_REPEATED); // [Word repeated] + } + // Check for invalid negative values for words F, N, P, T, and S. + // NOTE: Negative value check is done here simply for code-efficiency. + if (bit(word_bit) & (bit(WORD_F) | bit(WORD_N) | bit(WORD_P) | bit(WORD_T) | bit(WORD_S))) { + if (value < 0.0) { + FAIL(STATUS_NEGATIVE_VALUE); // [Word value cannot be negative] + } + } + value_words |= bit(word_bit); // Flag to indicate parameter assigned. } } // Parsing complete! @@ -573,14 +548,14 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // command has been sent. If so, set axis command to current motion mode. if (axis_words) { if (!axis_command) { - axis_command = AXIS_COMMAND_MOTION_MODE; // Assign implicit motion-mode + axis_command = AXIS_COMMAND_MOTION_MODE; // Assign implicit motion-mode } } // Check for valid line number N value. if (bit_istrue(value_words, bit(WORD_N))) { // Line number value cannot be less than zero (done) or greater than max line number. if (gc_block.values.n > MAX_LINE_NUMBER) { - FAIL(STATUS_GCODE_INVALID_LINE_NUMBER); // [Exceeds max line number] + FAIL(STATUS_GCODE_INVALID_LINE_NUMBER); // [Exceeds max line number] } } // bit_false(value_words,bit(WORD_N)); // NOTE: Single-meaning value word. Set at end of error-checking. @@ -600,12 +575,12 @@ uint8_t gc_execute_line(char* line, uint8_t client) { if (gc_block.modal.units == UNITS_MODE_INCHES) gc_block.values.f *= MM_PER_INCH; } else { - if (gc_block.modal.feed_rate == FEED_RATE_MODE_INVERSE_TIME) { // = G93 + if (gc_block.modal.feed_rate == FEED_RATE_MODE_INVERSE_TIME) { // = G93 // NOTE: G38 can also operate in inverse time, but is undefined as an error. Missing F word check added here. if (axis_command == AXIS_COMMAND_MOTION_MODE) { if ((gc_block.modal.motion != MOTION_MODE_NONE) || (gc_block.modal.motion != MOTION_MODE_SEEK)) { if (bit_isfalse(value_words, bit(WORD_F))) { - FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); // [F word missing] + FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); // [F word missing] } } } @@ -620,33 +595,34 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // value in the block. If no F word is passed with a motion command that requires a feed rate, this will error // out in the motion modes error-checking. However, if no F word is passed with NO motion command that requires // a feed rate, we simply move on and the state feed rate value gets updated to zero and remains undefined. - } else { // = G94 + } else { // = G94 // - In units per mm mode: If F word passed, ensure value is in mm/min, otherwise push last state value. - if (gc_state.modal.feed_rate == FEED_RATE_MODE_UNITS_PER_MIN) { // Last state is also G94 + if (gc_state.modal.feed_rate == FEED_RATE_MODE_UNITS_PER_MIN) { // Last state is also G94 if (bit_istrue(value_words, bit(WORD_F))) { if (gc_block.modal.units == UNITS_MODE_INCHES) gc_block.values.f *= MM_PER_INCH; } else { - gc_block.values.f = gc_state.feed_rate; // Push last state feed rate + gc_block.values.f = gc_state.feed_rate; // Push last state feed rate } - } // Else, switching to G94 from G93, so don't push last state feed rate. Its undefined or the passed F word value. + } // Else, switching to G94 from G93, so don't push last state feed rate. Its undefined or the passed F word value. } } // bit_false(value_words,bit(WORD_F)); // NOTE: Single-meaning value word. Set at end of error-checking. // [4. Set spindle speed ]: S is negative (done.) if (bit_isfalse(value_words, bit(WORD_S))) gc_block.values.s = gc_state.spindle_speed; - // bit_false(value_words,bit(WORD_S)); // NOTE: Single-meaning value word. Set at end of error-checking. - // [5. Select tool ]: NOT SUPPORTED. Only tracks value. T is negative (done.) Not an integer. Greater than max tool value. - // bit_false(value_words,bit(WORD_T)); // NOTE: Single-meaning value word. Set at end of error-checking. - // [6. Change tool ]: N/A - // [7. Spindle control ]: N/A - // [8. Coolant control ]: N/A - // [9. Enable/disable feed rate or spindle overrides ]: NOT SUPPORTED. + // bit_false(value_words,bit(WORD_S)); // NOTE: Single-meaning value word. Set at end of error-checking. + // [5. Select tool ]: NOT SUPPORTED. Only tracks value. T is negative (done.) Not an integer. Greater than max tool value. + // bit_false(value_words,bit(WORD_T)); // NOTE: Single-meaning value word. Set at end of error-checking. + // [6. Change tool ]: N/A + // [7. Spindle control ]: N/A + // [8. Coolant control ]: N/A + // [9. Enable/disable feed rate or spindle overrides ]: NOT SUPPORTED. #ifdef ENABLE_PARKING_OVERRIDE_CONTROL - if (bit_istrue(command_words, bit(MODAL_GROUP_M9))) { // Already set as enabled in parser. + if (bit_istrue(command_words, bit(MODAL_GROUP_M9))) { // Already set as enabled in parser. if (bit_istrue(value_words, bit(WORD_P))) { - if (gc_block.values.p == 0.0) gc_block.modal.override = OVERRIDE_DISABLED; + if (gc_block.values.p == 0.0) + gc_block.modal.override = OVERRIDE_DISABLED; bit_false(value_words, bit(WORD_P)); } } @@ -654,38 +630,38 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // [10. Dwell ]: P value missing. P is negative (done.) NOTE: See below. if (gc_block.non_modal_command == NON_MODAL_DWELL) { if (bit_isfalse(value_words, bit(WORD_P))) { - FAIL(STATUS_GCODE_VALUE_WORD_MISSING); // [P word missing] + FAIL(STATUS_GCODE_VALUE_WORD_MISSING); // [P word missing] } bit_false(value_words, bit(WORD_P)); } - if ((gc_block.modal.io_control == NON_MODAL_IO_ENABLE) || (gc_block.modal.io_control == NON_MODAL_IO_DISABLE)) { + if ((gc_block.modal.io_control == NON_MODAL_IO_ENABLE) || (gc_block.modal.io_control == NON_MODAL_IO_DISABLE)) { if (bit_isfalse(value_words, bit(WORD_P))) { - FAIL(STATUS_GCODE_VALUE_WORD_MISSING); // [P word missing] + FAIL(STATUS_GCODE_VALUE_WORD_MISSING); // [P word missing] } bit_false(value_words, bit(WORD_P)); } // [11. Set active plane ]: N/A switch (gc_block.modal.plane_select) { - case PLANE_SELECT_XY: - axis_0 = X_AXIS; - axis_1 = Y_AXIS; - axis_linear = Z_AXIS; - break; - case PLANE_SELECT_ZX: - axis_0 = Z_AXIS; - axis_1 = X_AXIS; - axis_linear = Y_AXIS; - break; - default: // case PLANE_SELECT_YZ: - axis_0 = Y_AXIS; - axis_1 = Z_AXIS; - axis_linear = X_AXIS; + case PLANE_SELECT_XY: + axis_0 = X_AXIS; + axis_1 = Y_AXIS; + axis_linear = Z_AXIS; + break; + case PLANE_SELECT_ZX: + axis_0 = Z_AXIS; + axis_1 = X_AXIS; + axis_linear = Y_AXIS; + break; + default: // case PLANE_SELECT_YZ: + axis_0 = Y_AXIS; + axis_1 = Z_AXIS; + axis_linear = X_AXIS; } // [12. Set length units ]: N/A // Pre-convert XYZ coordinate values to millimeters, if applicable. uint8_t idx; if (gc_block.modal.units == UNITS_MODE_INCHES) { - for (idx = 0; idx < N_AXIS; idx++) { // Axes indices are consistent, so loop may be used. + for (idx = 0; idx < N_AXIS; idx++) { // Axes indices are consistent, so loop may be used. if (bit_istrue(axis_words, bit(idx))) gc_block.values.xyz[idx] *= MM_PER_INCH; } @@ -714,7 +690,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { memcpy(block_coord_system, gc_state.coord_system, sizeof(gc_state.coord_system)); if (bit_istrue(command_words, bit(MODAL_GROUP_G12))) { // Check if called in block if (gc_block.modal.coord_select > N_COORDINATE_SYSTEM) { - FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); // [Greater than N sys] + FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); // [Greater than N sys] } if (gc_state.modal.coord_select != gc_block.modal.coord_select) { if (!(settings_read_coord_data(gc_block.modal.coord_select, block_coord_system))) @@ -730,148 +706,148 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // the axis value, G92 similarly to G10 L20, and G28/30 as an intermediate target position that observes // all the current coordinate system and G92 offsets. switch (gc_block.non_modal_command) { - case NON_MODAL_SET_COORDINATE_DATA: - // [G10 Errors]: L missing and is not 2 or 20. P word missing. (Negative P value done.) - // [G10 L2 Errors]: R word NOT SUPPORTED. P value not 0 to nCoordSys(max 9). Axis words missing. - // [G10 L20 Errors]: P must be 0 to nCoordSys(max 9). Axis words missing. - if (!axis_words) { - FAIL(STATUS_GCODE_NO_AXIS_WORDS) - }; // [No axis words] - if (bit_isfalse(value_words, (bit(WORD_P) | bit(WORD_L)))) { - FAIL(STATUS_GCODE_VALUE_WORD_MISSING); // [P/L word missing] - } - coord_select = trunc(gc_block.values.p); // Convert p value to int. - if (coord_select > N_COORDINATE_SYSTEM) { - FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); // [Greater than N sys] - } - if (gc_block.values.l != 20) { - if (gc_block.values.l == 2) { - if (bit_istrue(value_words, bit(WORD_R))) { - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [G10 L2 R not supported] - } - } else { - FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported L] + case NON_MODAL_SET_COORDINATE_DATA: + // [G10 Errors]: L missing and is not 2 or 20. P word missing. (Negative P value done.) + // [G10 L2 Errors]: R word NOT SUPPORTED. P value not 0 to nCoordSys(max 9). Axis words missing. + // [G10 L20 Errors]: P must be 0 to nCoordSys(max 9). Axis words missing. + if (!axis_words) { + FAIL(STATUS_GCODE_NO_AXIS_WORDS) + }; // [No axis words] + if (bit_isfalse(value_words, (bit(WORD_P) | bit(WORD_L)))) { + FAIL(STATUS_GCODE_VALUE_WORD_MISSING); // [P/L word missing] } - } - bit_false(value_words, (bit(WORD_L) | bit(WORD_P))); - // Determine coordinate system to change and try to load from EEPROM. - if (coord_select > 0) { - coord_select--; // Adjust P1-P6 index to EEPROM coordinate data indexing. - } else { - coord_select = gc_block.modal.coord_select; // Index P0 as the active coordinate system - } - // NOTE: Store parameter data in IJK values. By rule, they are not in use with this command. - // FIXME: Instead of IJK, we'd better use: float vector[N_AXIS]; // [DG] - if (!settings_read_coord_data(coord_select, gc_block.values.ijk)) { - FAIL(STATUS_SETTING_READ_FAIL); // [EEPROM read fail] - } - // Pre-calculate the coordinate data changes. - for (idx = 0; idx < N_AXIS; idx++) { // Axes indices are consistent, so loop may be used. - // Update axes defined only in block. Always in machine coordinates. Can change non-active system. - if (bit_istrue(axis_words, bit(idx))) { - if (gc_block.values.l == 20) { - // L20: Update coordinate system axis at current position (with modifiers) with programmed value - // WPos = MPos - WCS - G92 - TLO -> WCS = MPos - G92 - TLO - WPos - gc_block.values.ijk[idx] = gc_state.position[idx] - gc_state.coord_offset[idx] - gc_block.values.xyz[idx]; - if (idx == TOOL_LENGTH_OFFSET_AXIS) - gc_block.values.ijk[idx] -= gc_state.tool_length_offset; + coord_select = trunc(gc_block.values.p); // Convert p value to int. + if (coord_select > N_COORDINATE_SYSTEM) { + FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); // [Greater than N sys] + } + if (gc_block.values.l != 20) { + if (gc_block.values.l == 2) { + if (bit_istrue(value_words, bit(WORD_R))) { + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [G10 L2 R not supported] + } } else { - // L2: Update coordinate system axis to programmed value. - gc_block.values.ijk[idx] = gc_block.values.xyz[idx]; + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported L] } - } // Else, keep current stored value. - } - break; - case NON_MODAL_SET_COORDINATE_OFFSET: - // [G92 Errors]: No axis words. - if (!axis_words) { - FAIL(STATUS_GCODE_NO_AXIS_WORDS); // [No axis words] - } - // Update axes defined only in block. Offsets current system to defined value. Does not update when - // active coordinate system is selected, but is still active unless G92.1 disables it. - for (idx = 0; idx < N_AXIS; idx++) { // Axes indices are consistent, so loop may be used. - if (bit_istrue(axis_words, bit(idx))) { - // WPos = MPos - WCS - G92 - TLO -> G92 = MPos - WCS - TLO - WPos - gc_block.values.xyz[idx] = gc_state.position[idx] - block_coord_system[idx] - gc_block.values.xyz[idx]; - if (idx == TOOL_LENGTH_OFFSET_AXIS) - gc_block.values.xyz[idx] -= gc_state.tool_length_offset; - } else - gc_block.values.xyz[idx] = gc_state.coord_offset[idx]; - } - break; - default: - // At this point, the rest of the explicit axis commands treat the axis values as the traditional - // target position with the coordinate system offsets, G92 offsets, absolute override, and distance - // modes applied. This includes the motion mode commands. We can now pre-compute the target position. - // NOTE: Tool offsets may be appended to these conversions when/if this feature is added. - if (axis_command != AXIS_COMMAND_TOOL_LENGTH_OFFSET) { // TLO block any axis command. - if (axis_words) { - for (idx = 0; idx < N_AXIS; idx++) { // Axes indices are consistent, so loop may be used to save flash space. - if (bit_isfalse(axis_words, bit(idx))) { - gc_block.values.xyz[idx] = gc_state.position[idx]; // No axis word in block. Keep same axis position. + } + bit_false(value_words, (bit(WORD_L) | bit(WORD_P))); + // Determine coordinate system to change and try to load from EEPROM. + if (coord_select > 0) { + coord_select--; // Adjust P1-P6 index to EEPROM coordinate data indexing. + } else { + coord_select = gc_block.modal.coord_select; // Index P0 as the active coordinate system + } + // NOTE: Store parameter data in IJK values. By rule, they are not in use with this command. + // FIXME: Instead of IJK, we'd better use: float vector[N_AXIS]; // [DG] + if (!settings_read_coord_data(coord_select, gc_block.values.ijk)) { + FAIL(STATUS_SETTING_READ_FAIL); // [EEPROM read fail] + } + // Pre-calculate the coordinate data changes. + for (idx = 0; idx < N_AXIS; idx++) { // Axes indices are consistent, so loop may be used. + // Update axes defined only in block. Always in machine coordinates. Can change non-active system. + if (bit_istrue(axis_words, bit(idx))) { + if (gc_block.values.l == 20) { + // L20: Update coordinate system axis at current position (with modifiers) with programmed value + // WPos = MPos - WCS - G92 - TLO -> WCS = MPos - G92 - TLO - WPos + gc_block.values.ijk[idx] = gc_state.position[idx] - gc_state.coord_offset[idx] - gc_block.values.xyz[idx]; + if (idx == TOOL_LENGTH_OFFSET_AXIS) + gc_block.values.ijk[idx] -= gc_state.tool_length_offset; } else { - // Update specified value according to distance mode or ignore if absolute override is active. - // NOTE: G53 is never active with G28/30 since they are in the same modal group. - if (gc_block.non_modal_command != NON_MODAL_ABSOLUTE_OVERRIDE) { - // Apply coordinate offsets based on distance mode. - if (gc_block.modal.distance == DISTANCE_MODE_ABSOLUTE) { - gc_block.values.xyz[idx] += block_coord_system[idx] + gc_state.coord_offset[idx]; - if (idx == TOOL_LENGTH_OFFSET_AXIS) - gc_block.values.xyz[idx] += gc_state.tool_length_offset; - } else // Incremental mode - gc_block.values.xyz[idx] += gc_state.position[idx]; + // L2: Update coordinate system axis to programmed value. + gc_block.values.ijk[idx] = gc_block.values.xyz[idx]; + } + } // Else, keep current stored value. + } + break; + case NON_MODAL_SET_COORDINATE_OFFSET: + // [G92 Errors]: No axis words. + if (!axis_words) { + FAIL(STATUS_GCODE_NO_AXIS_WORDS); // [No axis words] + } + // Update axes defined only in block. Offsets current system to defined value. Does not update when + // active coordinate system is selected, but is still active unless G92.1 disables it. + for (idx = 0; idx < N_AXIS; idx++) { // Axes indices are consistent, so loop may be used. + if (bit_istrue(axis_words, bit(idx))) { + // WPos = MPos - WCS - G92 - TLO -> G92 = MPos - WCS - TLO - WPos + gc_block.values.xyz[idx] = gc_state.position[idx] - block_coord_system[idx] - gc_block.values.xyz[idx]; + if (idx == TOOL_LENGTH_OFFSET_AXIS) + gc_block.values.xyz[idx] -= gc_state.tool_length_offset; + } else + gc_block.values.xyz[idx] = gc_state.coord_offset[idx]; + } + break; + default: + // At this point, the rest of the explicit axis commands treat the axis values as the traditional + // target position with the coordinate system offsets, G92 offsets, absolute override, and distance + // modes applied. This includes the motion mode commands. We can now pre-compute the target position. + // NOTE: Tool offsets may be appended to these conversions when/if this feature is added. + if (axis_command != AXIS_COMMAND_TOOL_LENGTH_OFFSET) { // TLO block any axis command. + if (axis_words) { + for (idx = 0; idx < N_AXIS; idx++) { // Axes indices are consistent, so loop may be used to save flash space. + if (bit_isfalse(axis_words, bit(idx))) { + gc_block.values.xyz[idx] = gc_state.position[idx]; // No axis word in block. Keep same axis position. + } else { + // Update specified value according to distance mode or ignore if absolute override is active. + // NOTE: G53 is never active with G28/30 since they are in the same modal group. + if (gc_block.non_modal_command != NON_MODAL_ABSOLUTE_OVERRIDE) { + // Apply coordinate offsets based on distance mode. + if (gc_block.modal.distance == DISTANCE_MODE_ABSOLUTE) { + gc_block.values.xyz[idx] += block_coord_system[idx] + gc_state.coord_offset[idx]; + if (idx == TOOL_LENGTH_OFFSET_AXIS) + gc_block.values.xyz[idx] += gc_state.tool_length_offset; + } else // Incremental mode + gc_block.values.xyz[idx] += gc_state.position[idx]; + } } } } } - } - // Check remaining non-modal commands for errors. - switch (gc_block.non_modal_command) { - case NON_MODAL_GO_HOME_0: // G28 - case NON_MODAL_GO_HOME_1: // G30 - // [G28/30 Errors]: Cutter compensation is enabled. - // Retreive G28/30 go-home position data (in machine coordinates) from EEPROM - // NOTE: Store parameter data in IJK values. By rule, they are not in use with this command. - if (gc_block.non_modal_command == NON_MODAL_GO_HOME_0) { - if (!settings_read_coord_data(SETTING_INDEX_G28, gc_block.values.ijk)) - FAIL(STATUS_SETTING_READ_FAIL); - } else { // == NON_MODAL_GO_HOME_1 - if (!settings_read_coord_data(SETTING_INDEX_G30, gc_block.values.ijk)) - FAIL(STATUS_SETTING_READ_FAIL); + // Check remaining non-modal commands for errors. + switch (gc_block.non_modal_command) { + case NON_MODAL_GO_HOME_0: // G28 + case NON_MODAL_GO_HOME_1: // G30 + // [G28/30 Errors]: Cutter compensation is enabled. + // Retreive G28/30 go-home position data (in machine coordinates) from EEPROM + // NOTE: Store parameter data in IJK values. By rule, they are not in use with this command. + if (gc_block.non_modal_command == NON_MODAL_GO_HOME_0) { + if (!settings_read_coord_data(SETTING_INDEX_G28, gc_block.values.ijk)) + FAIL(STATUS_SETTING_READ_FAIL); + } else { // == NON_MODAL_GO_HOME_1 + if (!settings_read_coord_data(SETTING_INDEX_G30, gc_block.values.ijk)) + FAIL(STATUS_SETTING_READ_FAIL); + } + if (axis_words) { + // Move only the axes specified in secondary move. + for (idx = 0; idx < N_AXIS; idx++) { + if (!(axis_words & bit(idx))) + gc_block.values.ijk[idx] = gc_state.position[idx]; + } + } else { + axis_command = AXIS_COMMAND_NONE; // Set to none if no intermediate motion. + } + break; + case NON_MODAL_SET_HOME_0: // G28.1 + case NON_MODAL_SET_HOME_1: // G30.1 + // [G28.1/30.1 Errors]: Cutter compensation is enabled. + // NOTE: If axis words are passed here, they are interpreted as an implicit motion mode. + break; + case NON_MODAL_RESET_COORDINATE_OFFSET: + // NOTE: If axis words are passed here, they are interpreted as an implicit motion mode. + break; + case NON_MODAL_ABSOLUTE_OVERRIDE: + // [G53 Errors]: G0 and G1 are not active. Cutter compensation is enabled. + // NOTE: All explicit axis word commands are in this modal group. So no implicit check necessary. + if (!(gc_block.modal.motion == MOTION_MODE_SEEK || gc_block.modal.motion == MOTION_MODE_LINEAR)) { + FAIL(STATUS_GCODE_G53_INVALID_MOTION_MODE); // [G53 G0/1 not active] + } + break; } - if (axis_words) { - // Move only the axes specified in secondary move. - for (idx = 0; idx < N_AXIS; idx++) { - if (!(axis_words & bit(idx))) - gc_block.values.ijk[idx] = gc_state.position[idx]; - } - } else { - axis_command = AXIS_COMMAND_NONE; // Set to none if no intermediate motion. - } - break; - case NON_MODAL_SET_HOME_0: // G28.1 - case NON_MODAL_SET_HOME_1: // G30.1 - // [G28.1/30.1 Errors]: Cutter compensation is enabled. - // NOTE: If axis words are passed here, they are interpreted as an implicit motion mode. - break; - case NON_MODAL_RESET_COORDINATE_OFFSET: - // NOTE: If axis words are passed here, they are interpreted as an implicit motion mode. - break; - case NON_MODAL_ABSOLUTE_OVERRIDE: - // [G53 Errors]: G0 and G1 are not active. Cutter compensation is enabled. - // NOTE: All explicit axis word commands are in this modal group. So no implicit check necessary. - if (!(gc_block.modal.motion == MOTION_MODE_SEEK || gc_block.modal.motion == MOTION_MODE_LINEAR)) { - FAIL(STATUS_GCODE_G53_INVALID_MOTION_MODE); // [G53 G0/1 not active] - } - break; - } } // [20. Motion modes ]: if (gc_block.modal.motion == MOTION_MODE_NONE) { // [G80 Errors]: Axis word are programmed while G80 is active. // NOTE: Even non-modal commands or TLO that use axis words will throw this strict error. if (axis_words) { - FAIL(STATUS_GCODE_AXIS_WORDS_EXIST); // [No axis words allowed] + FAIL(STATUS_GCODE_AXIS_WORDS_EXIST); // [No axis words allowed] } // Check remaining motion modes, if axis word are implicit (exist and not used by G10/28/30/92), or // was explicitly commanded in the g-code block. @@ -886,43 +862,42 @@ uint8_t gc_execute_line(char* line, uint8_t client) { } else { // Check if feed rate is defined for the motion modes that require it. if (gc_block.values.f == 0.0) { - FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); // [Feed rate undefined] + FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); // [Feed rate undefined] } switch (gc_block.modal.motion) { - case MOTION_MODE_LINEAR: - // [G1 Errors]: Feed rate undefined. Axis letter not configured or without real value. - // Axis words are optional. If missing, set axis command flag to ignore execution. - if (!axis_words) - axis_command = AXIS_COMMAND_NONE; - break; - case MOTION_MODE_CW_ARC: - gc_parser_flags |= GC_PARSER_ARC_IS_CLOCKWISE; // No break intentional. - case MOTION_MODE_CCW_ARC: - // [G2/3 Errors All-Modes]: Feed rate undefined. - // [G2/3 Radius-Mode Errors]: No axis words in selected plane. Target point is same as current. - // [G2/3 Offset-Mode Errors]: No axis words and/or offsets in selected plane. The radius to the current - // point and the radius to the target point differs more than 0.002mm (EMC def. 0.5mm OR 0.005mm and 0.1% radius). - // [G2/3 Full-Circle-Mode Errors]: NOT SUPPORTED. Axis words exist. No offsets programmed. P must be an integer. - // NOTE: Both radius and offsets are required for arc tracing and are pre-computed with the error-checking. - if (!axis_words) { - FAIL(STATUS_GCODE_NO_AXIS_WORDS); // [No axis words] - } - if (!(axis_words & (bit(axis_0) | bit(axis_1)))) { - FAIL(STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE); // [No axis words in plane] - } - // Calculate the change in position along each selected axis - float x, y; - x = gc_block.values.xyz[axis_0] - gc_state.position[axis_0]; // Delta x between current position and target - y = gc_block.values.xyz[axis_1] - gc_state.position[axis_1]; // Delta y between current position and target - if (value_words & bit(WORD_R)) { // Arc Radius Mode - bit_false(value_words, bit(WORD_R)); - if (isequal_position_vector(gc_state.position, gc_block.values.xyz)) { - FAIL(STATUS_GCODE_INVALID_TARGET); // [Invalid target] + case MOTION_MODE_LINEAR: + // [G1 Errors]: Feed rate undefined. Axis letter not configured or without real value. + // Axis words are optional. If missing, set axis command flag to ignore execution. + if (!axis_words) + axis_command = AXIS_COMMAND_NONE; + break; + case MOTION_MODE_CW_ARC: gc_parser_flags |= GC_PARSER_ARC_IS_CLOCKWISE; // No break intentional. + case MOTION_MODE_CCW_ARC: + // [G2/3 Errors All-Modes]: Feed rate undefined. + // [G2/3 Radius-Mode Errors]: No axis words in selected plane. Target point is same as current. + // [G2/3 Offset-Mode Errors]: No axis words and/or offsets in selected plane. The radius to the current + // point and the radius to the target point differs more than 0.002mm (EMC def. 0.5mm OR 0.005mm and 0.1% radius). + // [G2/3 Full-Circle-Mode Errors]: NOT SUPPORTED. Axis words exist. No offsets programmed. P must be an integer. + // NOTE: Both radius and offsets are required for arc tracing and are pre-computed with the error-checking. + if (!axis_words) { + FAIL(STATUS_GCODE_NO_AXIS_WORDS); // [No axis words] } - // Convert radius value to proper units. - if (gc_block.modal.units == UNITS_MODE_INCHES) - gc_block.values.r *= MM_PER_INCH; - /* We need to calculate the center of the circle that has the designated radius and passes + if (!(axis_words & (bit(axis_0) | bit(axis_1)))) { + FAIL(STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE); // [No axis words in plane] + } + // Calculate the change in position along each selected axis + float x, y; + x = gc_block.values.xyz[axis_0] - gc_state.position[axis_0]; // Delta x between current position and target + y = gc_block.values.xyz[axis_1] - gc_state.position[axis_1]; // Delta y between current position and target + if (value_words & bit(WORD_R)) { // Arc Radius Mode + bit_false(value_words, bit(WORD_R)); + if (isequal_position_vector(gc_state.position, gc_block.values.xyz)) { + FAIL(STATUS_GCODE_INVALID_TARGET); // [Invalid target] + } + // Convert radius value to proper units. + if (gc_block.modal.units == UNITS_MODE_INCHES) + gc_block.values.r *= MM_PER_INCH; + /* We need to calculate the center of the circle that has the designated radius and passes through both the current position and the target position. This method calculates the following set of equations where [x,y] is the vector from current to target position, d == magnitude of that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to @@ -969,18 +944,18 @@ uint8_t gc_execute_line(char* line, uint8_t client) { i = (x - (y * h_x2_div_d))/2 j = (y + (x * h_x2_div_d))/2 */ - // First, use h_x2_div_d to compute 4*h^2 to check if it is negative or r is smaller - // than d. If so, the sqrt of a negative number is complex and error out. - float h_x2_div_d = 4.0 * gc_block.values.r * gc_block.values.r - x * x - y * y; - if (h_x2_div_d < 0) { - FAIL(STATUS_GCODE_ARC_RADIUS_ERROR); // [Arc radius error] - } - // Finish computing h_x2_div_d. - h_x2_div_d = -sqrt(h_x2_div_d) / hypot_f(x, y); // == -(h * 2 / d) - // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below) - if (gc_block.modal.motion == MOTION_MODE_CCW_ARC) - h_x2_div_d = -h_x2_div_d; - /* The counter clockwise circle lies to the left of the target direction. When offset is positive, + // First, use h_x2_div_d to compute 4*h^2 to check if it is negative or r is smaller + // than d. If so, the sqrt of a negative number is complex and error out. + float h_x2_div_d = 4.0 * gc_block.values.r * gc_block.values.r - x * x - y * y; + if (h_x2_div_d < 0) { + FAIL(STATUS_GCODE_ARC_RADIUS_ERROR); // [Arc radius error] + } + // Finish computing h_x2_div_d. + h_x2_div_d = -sqrt(h_x2_div_d) / hypot_f(x, y); // == -(h * 2 / d) + // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below) + if (gc_block.modal.motion == MOTION_MODE_CCW_ARC) + h_x2_div_d = -h_x2_div_d; + /* The counter clockwise circle lies to the left of the target direction. When offset is positive, the left hand circle will be generated - when it is negative the right hand circle is generated. T <-- Target position @@ -995,66 +970,64 @@ uint8_t gc_execute_line(char* line, uint8_t client) { C <-- Current position */ - // Negative R is g-code-alese for "I want a circle with more than 180 degrees of travel" (go figure!), - // even though it is advised against ever generating such circles in a single line of g-code. By - // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of - // travel and thus we get the unadvisably long arcs as prescribed. - if (gc_block.values.r < 0) { - h_x2_div_d = -h_x2_div_d; - gc_block.values.r = -gc_block.values.r; // Finished with r. Set to positive for mc_arc - } - // Complete the operation by calculating the actual center of the arc - gc_block.values.ijk[axis_0] = 0.5 * (x - (y * h_x2_div_d)); - gc_block.values.ijk[axis_1] = 0.5 * (y + (x * h_x2_div_d)); - } else { // Arc Center Format Offset Mode - if (!(ijk_words & (bit(axis_0) | bit(axis_1)))) { - FAIL(STATUS_GCODE_NO_OFFSETS_IN_PLANE); // [No offsets in plane] - } - bit_false(value_words, (bit(WORD_I) | bit(WORD_J) | bit(WORD_K))); - // Convert IJK values to proper units. - if (gc_block.modal.units == UNITS_MODE_INCHES) { - for (idx = 0; idx < N_AXIS; idx++) { // Axes indices are consistent, so loop may be used to save flash space. - if (ijk_words & bit(idx)) - gc_block.values.ijk[idx] *= MM_PER_INCH; + // Negative R is g-code-alese for "I want a circle with more than 180 degrees of travel" (go figure!), + // even though it is advised against ever generating such circles in a single line of g-code. By + // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of + // travel and thus we get the unadvisably long arcs as prescribed. + if (gc_block.values.r < 0) { + h_x2_div_d = -h_x2_div_d; + gc_block.values.r = -gc_block.values.r; // Finished with r. Set to positive for mc_arc + } + // Complete the operation by calculating the actual center of the arc + gc_block.values.ijk[axis_0] = 0.5 * (x - (y * h_x2_div_d)); + gc_block.values.ijk[axis_1] = 0.5 * (y + (x * h_x2_div_d)); + } else { // Arc Center Format Offset Mode + if (!(ijk_words & (bit(axis_0) | bit(axis_1)))) { + FAIL(STATUS_GCODE_NO_OFFSETS_IN_PLANE); // [No offsets in plane] + } + bit_false(value_words, (bit(WORD_I) | bit(WORD_J) | bit(WORD_K))); + // Convert IJK values to proper units. + if (gc_block.modal.units == UNITS_MODE_INCHES) { + for (idx = 0; idx < N_AXIS; idx++) { // Axes indices are consistent, so loop may be used to save flash space. + if (ijk_words & bit(idx)) + gc_block.values.ijk[idx] *= MM_PER_INCH; + } + } + // Arc radius from center to target + x -= gc_block.values.ijk[axis_0]; // Delta x between circle center and target + y -= gc_block.values.ijk[axis_1]; // Delta y between circle center and target + float target_r = hypot_f(x, y); + // Compute arc radius for mc_arc. Defined from current location to center. + gc_block.values.r = hypot_f(gc_block.values.ijk[axis_0], gc_block.values.ijk[axis_1]); + // Compute difference between current location and target radii for final error-checks. + float delta_r = fabs(target_r - gc_block.values.r); + if (delta_r > 0.005) { + if (delta_r > 0.5) { + FAIL(STATUS_GCODE_INVALID_TARGET); // [Arc definition error] > 0.5mm + } + if (delta_r > (0.001 * gc_block.values.r)) { + FAIL(STATUS_GCODE_INVALID_TARGET); // [Arc definition error] > 0.005mm AND 0.1% radius + } } } - // Arc radius from center to target - x -= gc_block.values.ijk[axis_0]; // Delta x between circle center and target - y -= gc_block.values.ijk[axis_1]; // Delta y between circle center and target - float target_r = hypot_f(x, y); - // Compute arc radius for mc_arc. Defined from current location to center. - gc_block.values.r = hypot_f(gc_block.values.ijk[axis_0], gc_block.values.ijk[axis_1]); - // Compute difference between current location and target radii for final error-checks. - float delta_r = fabs(target_r - gc_block.values.r); - if (delta_r > 0.005) { - if (delta_r > 0.5) { - FAIL(STATUS_GCODE_INVALID_TARGET); // [Arc definition error] > 0.5mm - } - if (delta_r > (0.001 * gc_block.values.r)) { - FAIL(STATUS_GCODE_INVALID_TARGET); // [Arc definition error] > 0.005mm AND 0.1% radius - } + break; + case MOTION_MODE_PROBE_TOWARD_NO_ERROR: + case MOTION_MODE_PROBE_AWAY_NO_ERROR: gc_parser_flags |= GC_PARSER_PROBE_IS_NO_ERROR; // No break intentional. + case MOTION_MODE_PROBE_TOWARD: + case MOTION_MODE_PROBE_AWAY: + if ((gc_block.modal.motion == MOTION_MODE_PROBE_AWAY) || (gc_block.modal.motion == MOTION_MODE_PROBE_AWAY_NO_ERROR)) + gc_parser_flags |= GC_PARSER_PROBE_IS_AWAY; + // [G38 Errors]: Target is same current. No axis words. Cutter compensation is enabled. Feed rate + // is undefined. Probe is triggered. NOTE: Probe check moved to probe cycle. Instead of returning + // an error, it issues an alarm to prevent further motion to the probe. It's also done there to + // allow the planner buffer to empty and move off the probe trigger before another probing cycle. + if (!axis_words) { + FAIL(STATUS_GCODE_NO_AXIS_WORDS); // [No axis words] } - } - break; - case MOTION_MODE_PROBE_TOWARD_NO_ERROR: - case MOTION_MODE_PROBE_AWAY_NO_ERROR: - gc_parser_flags |= GC_PARSER_PROBE_IS_NO_ERROR; // No break intentional. - case MOTION_MODE_PROBE_TOWARD: - case MOTION_MODE_PROBE_AWAY: - if ((gc_block.modal.motion == MOTION_MODE_PROBE_AWAY) || - (gc_block.modal.motion == MOTION_MODE_PROBE_AWAY_NO_ERROR)) - gc_parser_flags |= GC_PARSER_PROBE_IS_AWAY; - // [G38 Errors]: Target is same current. No axis words. Cutter compensation is enabled. Feed rate - // is undefined. Probe is triggered. NOTE: Probe check moved to probe cycle. Instead of returning - // an error, it issues an alarm to prevent further motion to the probe. It's also done there to - // allow the planner buffer to empty and move off the probe trigger before another probing cycle. - if (!axis_words) { - FAIL(STATUS_GCODE_NO_AXIS_WORDS); // [No axis words] - } - if (isequal_position_vector(gc_state.position, gc_block.values.xyz)) { - FAIL(STATUS_GCODE_INVALID_TARGET); // [Invalid target] - } - break; + if (isequal_position_vector(gc_state.position, gc_block.values.xyz)) { + FAIL(STATUS_GCODE_INVALID_TARGET); // [Invalid target] + } + break; } } } @@ -1065,13 +1038,13 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // Jogging only uses the F feed rate and XYZ value words. N is valid, but S and T are invalid. bit_false(value_words, (bit(WORD_N) | bit(WORD_F))); } else { - bit_false(value_words, (bit(WORD_N) | bit(WORD_F) | bit(WORD_S) | bit(WORD_T))); // Remove single-meaning value words. + bit_false(value_words, (bit(WORD_N) | bit(WORD_F) | bit(WORD_S) | bit(WORD_T))); // Remove single-meaning value words. } if (axis_command) { - bit_false(value_words, (bit(WORD_X) | bit(WORD_Y) | bit(WORD_Z) | bit(WORD_A) | bit(WORD_B) | bit(WORD_C))); // Remove axis words. + bit_false(value_words, (bit(WORD_X) | bit(WORD_Y) | bit(WORD_Z) | bit(WORD_A) | bit(WORD_B) | bit(WORD_C))); // Remove axis words. } if (value_words) { - FAIL(STATUS_GCODE_UNUSED_WORDS); // [Unused words] + FAIL(STATUS_GCODE_UNUSED_WORDS); // [Unused words] } /* ------------------------------------------------------------------------------------- STEP 4: EXECUTE!! @@ -1079,9 +1052,9 @@ uint8_t gc_execute_line(char* line, uint8_t client) { need to update the state and execute the block according to the order-of-execution. */ // Initialize planner data struct for motion blocks. - plan_line_data_t plan_data; + plan_line_data_t plan_data; plan_line_data_t* pl_data = &plan_data; - memset(pl_data, 0, sizeof(plan_line_data_t)); // Zero pl_data struct + memset(pl_data, 0, sizeof(plan_line_data_t)); // Zero pl_data struct // Intercept jog commands and complete error checking for valid jog commands and execute. // NOTE: G-code parser state is not updated, except the position to ensure sequential jog // targets are computed correctly. The final parser position after a jog is updated in @@ -1096,16 +1069,16 @@ uint8_t gc_execute_line(char* line, uint8_t client) { FAIL(STATUS_INVALID_JOG_COMMAND); // Initialize planner data to current spindle and coolant modal state. pl_data->spindle_speed = gc_state.spindle_speed; - plan_data.condition = (gc_state.modal.spindle | gc_state.modal.coolant); - uint8_t status = jog_execute(&plan_data, &gc_block); + plan_data.condition = (gc_state.modal.spindle | gc_state.modal.coolant); + uint8_t status = jog_execute(&plan_data, &gc_block); if (status == STATUS_OK) memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); return (status); } // If in laser mode, setup laser power based on current and past parser conditions. if (laser_mode->get()) { - if (!((gc_block.modal.motion == MOTION_MODE_LINEAR) || (gc_block.modal.motion == MOTION_MODE_CW_ARC) - || (gc_block.modal.motion == MOTION_MODE_CCW_ARC))) + if (!((gc_block.modal.motion == MOTION_MODE_LINEAR) || (gc_block.modal.motion == MOTION_MODE_CW_ARC) || + (gc_block.modal.motion == MOTION_MODE_CCW_ARC))) gc_parser_flags |= GC_PARSER_LASER_DISABLE; // Any motion mode with axis words is allowed to be passed from a spindle speed update. // NOTE: G1 and G0 without axis words sets axis_command to none. G28/30 are intentionally omitted. @@ -1116,10 +1089,10 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // M3 constant power laser requires planner syncs to update the laser when changing between // a G1/2/3 motion mode state and vice versa when there is no motion in the line. if (gc_state.modal.spindle == SPINDLE_ENABLE_CW) { - if ((gc_state.modal.motion == MOTION_MODE_LINEAR) || (gc_state.modal.motion == MOTION_MODE_CW_ARC) - || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) { + if ((gc_state.modal.motion == MOTION_MODE_LINEAR) || (gc_state.modal.motion == MOTION_MODE_CW_ARC) || + (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) { if (bit_istrue(gc_parser_flags, GC_PARSER_LASER_DISABLE)) { - gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC; // Change from G1/2/3 motion mode. + gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC; // Change from G1/2/3 motion mode. } } else { // When changing to a G1 motion mode without axis words from a non-G1/2/3 motion mode. @@ -1133,17 +1106,17 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // NOTE: If no line number is present, the value is zero. gc_state.line_number = gc_block.values.n; #ifdef USE_LINE_NUMBERS - pl_data->line_number = gc_state.line_number; // Record data for planner use. + pl_data->line_number = gc_state.line_number; // Record data for planner use. #endif // [1. Comments feedback ]: NOT SUPPORTED // [2. Set feed rate mode ]: gc_state.modal.feed_rate = gc_block.modal.feed_rate; if (gc_state.modal.feed_rate) { - pl_data->condition |= PL_COND_FLAG_INVERSE_TIME; // Set condition flag for planner use. + pl_data->condition |= PL_COND_FLAG_INVERSE_TIME; // Set condition flag for planner use. } // [3. Set feed rate ]: - gc_state.feed_rate = gc_block.values.f; // Always copy this value. See feed rate error-checking. - pl_data->feed_rate = gc_state.feed_rate; // Record data for planner use. + gc_state.feed_rate = gc_block.values.f; // Always copy this value. See feed rate error-checking. + pl_data->feed_rate = gc_state.feed_rate; // Record data for planner use. // [4. Set spindle speed ]: if ((gc_state.spindle_speed != gc_block.values.s) || bit_istrue(gc_parser_flags, GC_PARSER_LASER_FORCE_SYNC)) { if (gc_state.modal.spindle != SPINDLE_DISABLE) { @@ -1154,12 +1127,12 @@ uint8_t gc_execute_line(char* line, uint8_t client) { spindle->spindle_sync(gc_state.modal.spindle, (uint32_t)gc_block.values.s); } } - gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state. + gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state. } // NOTE: Pass zero spindle speed for all restricted laser motions. if (bit_isfalse(gc_parser_flags, GC_PARSER_LASER_DISABLE)) { - pl_data->spindle_speed = gc_state.spindle_speed; // Record data for planner use. - } // else { pl_data->spindle_speed = 0.0; } // Initialized as zero already. + pl_data->spindle_speed = gc_state.spindle_speed; // Record data for planner use. + } // else { pl_data->spindle_speed = 0.0; } // Initialized as zero already. // [5. Select tool ]: NOT SUPPORTED. Only tracks tool value. // gc_state.tool = gc_block.values.t; // [6. Change tool ]: NOT SUPPORTED @@ -1176,7 +1149,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { spindle->spindle_sync(gc_block.modal.spindle, (uint32_t)pl_data->spindle_speed); gc_state.modal.spindle = gc_block.modal.spindle; } - pl_data->condition |= gc_state.modal.spindle; // Set condition flag for planner use. + pl_data->condition |= gc_state.modal.spindle; // Set condition flag for planner use. // [8. Coolant control ]: if (gc_state.modal.coolant != gc_block.modal.coolant) { // NOTE: Coolant M-codes are modal. Only one command per line is allowed. But, multiple states @@ -1187,7 +1160,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { else gc_state.modal.coolant |= gc_block.modal.coolant; } - pl_data->condition |= gc_state.modal.coolant; // Set condition flag for planner use. + pl_data->condition |= gc_state.modal.coolant; // Set condition flag for planner use. // turn on/off an i/o pin if ((gc_block.modal.io_control == NON_MODAL_IO_ENABLE) || (gc_block.modal.io_control == NON_MODAL_IO_DISABLE)) { if (gc_block.values.p <= MAX_USER_DIGITAL_PIN) @@ -1217,7 +1190,7 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // axis of the block XYZ value array. if (axis_command == AXIS_COMMAND_TOOL_LENGTH_OFFSET) { // Indicates a change. gc_state.modal.tool_length = gc_block.modal.tool_length; - if (gc_state.modal.tool_length == TOOL_LENGTH_OFFSET_CANCEL) // G49 + if (gc_state.modal.tool_length == TOOL_LENGTH_OFFSET_CANCEL) // G49 gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS] = 0.0; // else G43.1 if (gc_state.tool_length_offset != gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS]) { @@ -1238,39 +1211,35 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // [18. Set retract mode ]: NOT SUPPORTED // [19. Go to predefined position, Set G10, or Set axis offsets ]: switch (gc_block.non_modal_command) { - case NON_MODAL_SET_COORDINATE_DATA: - settings_write_coord_data(coord_select, gc_block.values.ijk); - // Update system coordinate system if currently active. - if (gc_state.modal.coord_select == coord_select) { - memcpy(gc_state.coord_system, gc_block.values.ijk, N_AXIS * sizeof(float)); + case NON_MODAL_SET_COORDINATE_DATA: + settings_write_coord_data(coord_select, gc_block.values.ijk); + // Update system coordinate system if currently active. + if (gc_state.modal.coord_select == coord_select) { + memcpy(gc_state.coord_system, gc_block.values.ijk, N_AXIS * sizeof(float)); + system_flag_wco_change(); + } + break; + case NON_MODAL_GO_HOME_0: + case NON_MODAL_GO_HOME_1: + // Move to intermediate position before going home. Obeys current coordinate system and offsets + // and absolute and incremental modes. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + if (axis_command) { + mc_line(gc_block.values.xyz, pl_data); // kinematics kinematics not used for homing righ now + } + mc_line(gc_block.values.ijk, pl_data); + memcpy(gc_state.position, gc_block.values.ijk, N_AXIS * sizeof(float)); + break; + case NON_MODAL_SET_HOME_0: settings_write_coord_data(SETTING_INDEX_G28, gc_state.position); break; + case NON_MODAL_SET_HOME_1: settings_write_coord_data(SETTING_INDEX_G30, gc_state.position); break; + case NON_MODAL_SET_COORDINATE_OFFSET: + memcpy(gc_state.coord_offset, gc_block.values.xyz, sizeof(gc_block.values.xyz)); system_flag_wco_change(); - } - break; - case NON_MODAL_GO_HOME_0: - case NON_MODAL_GO_HOME_1: - // Move to intermediate position before going home. Obeys current coordinate system and offsets - // and absolute and incremental modes. - pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. - if (axis_command) { - mc_line(gc_block.values.xyz, pl_data); // kinematics kinematics not used for homing righ now - } - mc_line(gc_block.values.ijk, pl_data); - memcpy(gc_state.position, gc_block.values.ijk, N_AXIS * sizeof(float)); - break; - case NON_MODAL_SET_HOME_0: - settings_write_coord_data(SETTING_INDEX_G28, gc_state.position); - break; - case NON_MODAL_SET_HOME_1: - settings_write_coord_data(SETTING_INDEX_G30, gc_state.position); - break; - case NON_MODAL_SET_COORDINATE_OFFSET: - memcpy(gc_state.coord_offset, gc_block.values.xyz, sizeof(gc_block.values.xyz)); - system_flag_wco_change(); - break; - case NON_MODAL_RESET_COORDINATE_OFFSET: - clear_vector(gc_state.coord_offset); // Disable G92 offsets by zeroing offset vector. - system_flag_wco_change(); - break; + break; + case NON_MODAL_RESET_COORDINATE_OFFSET: + clear_vector(gc_state.coord_offset); // Disable G92 offsets by zeroing offset vector. + system_flag_wco_change(); + break; } // [20. Motion modes ]: // NOTE: Commands G10,G28,G30,G92 lock out and prevent axis words from use in motion modes. @@ -1283,12 +1252,19 @@ uint8_t gc_execute_line(char* line, uint8_t client) { //mc_line(gc_block.values.xyz, pl_data); mc_line_kins(gc_block.values.xyz, pl_data, gc_state.position); } else if (gc_state.modal.motion == MOTION_MODE_SEEK) { - pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. //mc_line(gc_block.values.xyz, pl_data); mc_line_kins(gc_block.values.xyz, pl_data, gc_state.position); } else if ((gc_state.modal.motion == MOTION_MODE_CW_ARC) || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) { - mc_arc(gc_block.values.xyz, pl_data, gc_state.position, gc_block.values.ijk, gc_block.values.r, - axis_0, axis_1, axis_linear, bit_istrue(gc_parser_flags, GC_PARSER_ARC_IS_CLOCKWISE)); + mc_arc(gc_block.values.xyz, + pl_data, + gc_state.position, + gc_block.values.ijk, + gc_block.values.r, + axis_0, + axis_1, + axis_linear, + bit_istrue(gc_parser_flags, GC_PARSER_ARC_IS_CLOCKWISE)); } else { // NOTE: gc_block.values.xyz is returned from mc_probe_cycle with the updated position value. So // upon a successful probing cycle, the machine position and the returned value should be the same. @@ -1301,10 +1277,10 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // motion control system might still be processing the action and the real tool position // in any intermediate location. if (gc_update_pos == GC_UPDATE_POS_TARGET) { - memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc_state.position[] = gc_block.values.xyz[] + memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc_state.position[] = gc_block.values.xyz[] } else if (gc_update_pos == GC_UPDATE_POS_SYSTEM) { - gc_sync_position(); // gc_state.position[] = sys_position - } // == GC_UPDATE_POS_NONE + gc_sync_position(); // gc_state.position[] = sys_position + } // == GC_UPDATE_POS_NONE } } // [21. Program flow ]: @@ -1312,43 +1288,43 @@ uint8_t gc_execute_line(char* line, uint8_t client) { // refill and can only be resumed by the cycle start run-time command. gc_state.modal.program_flow = gc_block.modal.program_flow; if (gc_state.modal.program_flow) { - protocol_buffer_synchronize(); // Sync and finish all remaining buffered motions before moving on. + protocol_buffer_synchronize(); // Sync and finish all remaining buffered motions before moving on. if (gc_state.modal.program_flow == PROGRAM_FLOW_PAUSED) { if (sys.state != STATE_CHECK_MODE) { - system_set_exec_state_flag(EXEC_FEED_HOLD); // Use feed hold for program pause. - protocol_execute_realtime(); // Execute suspend. + system_set_exec_state_flag(EXEC_FEED_HOLD); // Use feed hold for program pause. + protocol_execute_realtime(); // Execute suspend. } - } else { // == PROGRAM_FLOW_COMPLETED + } else { // == PROGRAM_FLOW_COMPLETED // Upon program complete, only a subset of g-codes reset to certain defaults, according to // LinuxCNC's program end descriptions and testing. Only modal groups [G-code 1,2,3,5,7,12] // and [M-code 7,8,9] reset to [G1,G17,G90,G94,G40,G54,M5,M9,M48]. The remaining modal groups // [G-code 4,6,8,10,13,14,15] and [M-code 4,5,6] and the modal words [F,S,T,H] do not reset. - gc_state.modal.motion = MOTION_MODE_LINEAR; + gc_state.modal.motion = MOTION_MODE_LINEAR; gc_state.modal.plane_select = PLANE_SELECT_XY; - gc_state.modal.distance = DISTANCE_MODE_ABSOLUTE; - gc_state.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN; + gc_state.modal.distance = DISTANCE_MODE_ABSOLUTE; + gc_state.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN; // gc_state.modal.cutter_comp = CUTTER_COMP_DISABLE; // Not supported. - gc_state.modal.coord_select = 0; // G54 - gc_state.modal.spindle = SPINDLE_DISABLE; - gc_state.modal.coolant = COOLANT_DISABLE; + gc_state.modal.coord_select = 0; // G54 + gc_state.modal.spindle = SPINDLE_DISABLE; + gc_state.modal.coolant = COOLANT_DISABLE; #ifdef ENABLE_PARKING_OVERRIDE_CONTROL -#ifdef DEACTIVATE_PARKING_UPON_INIT +# ifdef DEACTIVATE_PARKING_UPON_INIT gc_state.modal.override = OVERRIDE_DISABLED; -#else +# else gc_state.modal.override = OVERRIDE_PARKING_MOTION; -#endif +# endif #endif // gc_state.modal.override = OVERRIDE_DISABLE; // Not supported. #ifdef RESTORE_OVERRIDES_AFTER_PROGRAM_END - sys.f_override = DEFAULT_FEED_OVERRIDE; - sys.r_override = DEFAULT_RAPID_OVERRIDE; + sys.f_override = DEFAULT_FEED_OVERRIDE; + sys.r_override = DEFAULT_RAPID_OVERRIDE; sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; #endif // Execute coordinate change and spindle/coolant stop. if (sys.state != STATE_CHECK_MODE) { if (!(settings_read_coord_data(gc_state.modal.coord_select, gc_state.coord_system))) FAIL(STATUS_SETTING_READ_FAIL); - system_flag_wco_change(); // Set to refresh immediately just in case something altered. + system_flag_wco_change(); // Set to refresh immediately just in case something altered. spindle->set_state(SPINDLE_DISABLE, 0); coolant_set_state(COOLANT_DISABLE); } @@ -1357,13 +1333,12 @@ uint8_t gc_execute_line(char* line, uint8_t client) { user_m30(); #endif } - gc_state.modal.program_flow = PROGRAM_FLOW_RUNNING; // Reset program flow. + gc_state.modal.program_flow = PROGRAM_FLOW_RUNNING; // Reset program flow. } // TODO: % to denote start of program. return (STATUS_OK); } - /* Not supported: diff --git a/Grbl_Esp32/gcode.h b/Grbl_Esp32/gcode.h index a1865b9e..22527b2c 100644 --- a/Grbl_Esp32/gcode.h +++ b/Grbl_Esp32/gcode.h @@ -30,24 +30,24 @@ // a unique motion. These are defined in the NIST RS274-NGC v3 g-code standard, available online, // and are similar/identical to other g-code interpreters by manufacturers (Haas,Fanuc,Mazak,etc). // NOTE: Modal group define values must be sequential and starting from zero. -#define MODAL_GROUP_G0 0 // [G4,G10,G28,G28.1,G30,G30.1,G53,G92,G92.1] Non-modal -#define MODAL_GROUP_G1 1 // [G0,G1,G2,G3,G38.2,G38.3,G38.4,G38.5,G80] Motion -#define MODAL_GROUP_G2 2 // [G17,G18,G19] Plane selection -#define MODAL_GROUP_G3 3 // [G90,G91] Distance mode -#define MODAL_GROUP_G4 4 // [G91.1] Arc IJK distance mode -#define MODAL_GROUP_G5 5 // [G93,G94] Feed rate mode -#define MODAL_GROUP_G6 6 // [G20,G21] Units -#define MODAL_GROUP_G7 7 // [G40] Cutter radius compensation mode. G41/42 NOT SUPPORTED. -#define MODAL_GROUP_G8 8 // [G43.1,G49] Tool length offset -#define MODAL_GROUP_G12 9 // [G54,G55,G56,G57,G58,G59] Coordinate system selection -#define MODAL_GROUP_G13 10 // [G61] Control mode +#define MODAL_GROUP_G0 0 // [G4,G10,G28,G28.1,G30,G30.1,G53,G92,G92.1] Non-modal +#define MODAL_GROUP_G1 1 // [G0,G1,G2,G3,G38.2,G38.3,G38.4,G38.5,G80] Motion +#define MODAL_GROUP_G2 2 // [G17,G18,G19] Plane selection +#define MODAL_GROUP_G3 3 // [G90,G91] Distance mode +#define MODAL_GROUP_G4 4 // [G91.1] Arc IJK distance mode +#define MODAL_GROUP_G5 5 // [G93,G94] Feed rate mode +#define MODAL_GROUP_G6 6 // [G20,G21] Units +#define MODAL_GROUP_G7 7 // [G40] Cutter radius compensation mode. G41/42 NOT SUPPORTED. +#define MODAL_GROUP_G8 8 // [G43.1,G49] Tool length offset +#define MODAL_GROUP_G12 9 // [G54,G55,G56,G57,G58,G59] Coordinate system selection +#define MODAL_GROUP_G13 10 // [G61] Control mode -#define MODAL_GROUP_M4 11 // [M0,M1,M2,M30] Stopping -#define MODAL_GROUP_M6 14 // [M6] Tool change -#define MODAL_GROUP_M7 12 // [M3,M4,M5] Spindle turning -#define MODAL_GROUP_M8 13 // [M7,M8,M9] Coolant control -#define MODAL_GROUP_M9 14 // [M56] Override control -#define MODAL_GROUP_M10 15 // [M62, M63] User Defined http://linuxcnc.org/docs/html/gcode/overview.html#_modal_groups +#define MODAL_GROUP_M4 11 // [M0,M1,M2,M30] Stopping +#define MODAL_GROUP_M6 14 // [M6] Tool change +#define MODAL_GROUP_M7 12 // [M3,M4,M5] Spindle turning +#define MODAL_GROUP_M8 13 // [M7,M8,M9] Coolant control +#define MODAL_GROUP_M9 14 // [M56] Override control +#define MODAL_GROUP_M10 15 // [M62, M63] User Defined http://linuxcnc.org/docs/html/gcode/overview.html#_modal_groups // #define OTHER_INPUT_F 14 // #define OTHER_INPUT_S 15 @@ -61,88 +61,88 @@ // to see how they are used, if you need to alter them. // Modal Group G0: Non-modal actions -#define NON_MODAL_NO_ACTION 0 // (Default: Must be zero) -#define NON_MODAL_DWELL 4 // G4 (Do not alter value) -#define NON_MODAL_SET_COORDINATE_DATA 10 // G10 (Do not alter value) -#define NON_MODAL_GO_HOME_0 28 // G28 (Do not alter value) -#define NON_MODAL_SET_HOME_0 38 // G28.1 (Do not alter value) -#define NON_MODAL_GO_HOME_1 30 // G30 (Do not alter value) -#define NON_MODAL_SET_HOME_1 40 // G30.1 (Do not alter value) -#define NON_MODAL_ABSOLUTE_OVERRIDE 53 // G53 (Do not alter value) -#define NON_MODAL_SET_COORDINATE_OFFSET 92 // G92 (Do not alter value) -#define NON_MODAL_RESET_COORDINATE_OFFSET 102 //G92.1 (Do not alter value) +#define NON_MODAL_NO_ACTION 0 // (Default: Must be zero) +#define NON_MODAL_DWELL 4 // G4 (Do not alter value) +#define NON_MODAL_SET_COORDINATE_DATA 10 // G10 (Do not alter value) +#define NON_MODAL_GO_HOME_0 28 // G28 (Do not alter value) +#define NON_MODAL_SET_HOME_0 38 // G28.1 (Do not alter value) +#define NON_MODAL_GO_HOME_1 30 // G30 (Do not alter value) +#define NON_MODAL_SET_HOME_1 40 // G30.1 (Do not alter value) +#define NON_MODAL_ABSOLUTE_OVERRIDE 53 // G53 (Do not alter value) +#define NON_MODAL_SET_COORDINATE_OFFSET 92 // G92 (Do not alter value) +#define NON_MODAL_RESET_COORDINATE_OFFSET 102 //G92.1 (Do not alter value) // Modal Group G1: Motion modes -#define MOTION_MODE_SEEK 0 // G0 (Default: Must be zero) -#define MOTION_MODE_LINEAR 1 // G1 (Do not alter value) -#define MOTION_MODE_CW_ARC 2 // G2 (Do not alter value) -#define MOTION_MODE_CCW_ARC 3 // G3 (Do not alter value) -#define MOTION_MODE_PROBE_TOWARD 140 // G38.2 (Do not alter value) -#define MOTION_MODE_PROBE_TOWARD_NO_ERROR 141 // G38.3 (Do not alter value) -#define MOTION_MODE_PROBE_AWAY 142 // G38.4 (Do not alter value) -#define MOTION_MODE_PROBE_AWAY_NO_ERROR 143 // G38.5 (Do not alter value) -#define MOTION_MODE_NONE 80 // G80 (Do not alter value) +#define MOTION_MODE_SEEK 0 // G0 (Default: Must be zero) +#define MOTION_MODE_LINEAR 1 // G1 (Do not alter value) +#define MOTION_MODE_CW_ARC 2 // G2 (Do not alter value) +#define MOTION_MODE_CCW_ARC 3 // G3 (Do not alter value) +#define MOTION_MODE_PROBE_TOWARD 140 // G38.2 (Do not alter value) +#define MOTION_MODE_PROBE_TOWARD_NO_ERROR 141 // G38.3 (Do not alter value) +#define MOTION_MODE_PROBE_AWAY 142 // G38.4 (Do not alter value) +#define MOTION_MODE_PROBE_AWAY_NO_ERROR 143 // G38.5 (Do not alter value) +#define MOTION_MODE_NONE 80 // G80 (Do not alter value) // Modal Group G2: Plane select -#define PLANE_SELECT_XY 0 // G17 (Default: Must be zero) -#define PLANE_SELECT_ZX 1 // G18 (Do not alter value) -#define PLANE_SELECT_YZ 2 // G19 (Do not alter value) +#define PLANE_SELECT_XY 0 // G17 (Default: Must be zero) +#define PLANE_SELECT_ZX 1 // G18 (Do not alter value) +#define PLANE_SELECT_YZ 2 // G19 (Do not alter value) // Modal Group G3: Distance mode -#define DISTANCE_MODE_ABSOLUTE 0 // G90 (Default: Must be zero) -#define DISTANCE_MODE_INCREMENTAL 1 // G91 (Do not alter value) +#define DISTANCE_MODE_ABSOLUTE 0 // G90 (Default: Must be zero) +#define DISTANCE_MODE_INCREMENTAL 1 // G91 (Do not alter value) // Modal Group G4: Arc IJK distance mode -#define DISTANCE_ARC_MODE_INCREMENTAL 0 // G91.1 (Default: Must be zero) +#define DISTANCE_ARC_MODE_INCREMENTAL 0 // G91.1 (Default: Must be zero) // Modal Group M4: Program flow -#define PROGRAM_FLOW_RUNNING 0 // (Default: Must be zero) -#define PROGRAM_FLOW_PAUSED 3 // M0 -#define PROGRAM_FLOW_OPTIONAL_STOP 1 // M1 NOTE: Not supported, but valid and ignored. -#define PROGRAM_FLOW_COMPLETED_M2 2 // M2 (Do not alter value) -#define PROGRAM_FLOW_COMPLETED_M30 30 // M30 (Do not alter value) +#define PROGRAM_FLOW_RUNNING 0 // (Default: Must be zero) +#define PROGRAM_FLOW_PAUSED 3 // M0 +#define PROGRAM_FLOW_OPTIONAL_STOP 1 // M1 NOTE: Not supported, but valid and ignored. +#define PROGRAM_FLOW_COMPLETED_M2 2 // M2 (Do not alter value) +#define PROGRAM_FLOW_COMPLETED_M30 30 // M30 (Do not alter value) // Modal Group G5: Feed rate mode -#define FEED_RATE_MODE_UNITS_PER_MIN 0 // G94 (Default: Must be zero) -#define FEED_RATE_MODE_INVERSE_TIME 1 // G93 (Do not alter value) +#define FEED_RATE_MODE_UNITS_PER_MIN 0 // G94 (Default: Must be zero) +#define FEED_RATE_MODE_INVERSE_TIME 1 // G93 (Do not alter value) // Modal Group G6: Units mode -#define UNITS_MODE_MM 0 // G21 (Default: Must be zero) -#define UNITS_MODE_INCHES 1 // G20 (Do not alter value) +#define UNITS_MODE_MM 0 // G21 (Default: Must be zero) +#define UNITS_MODE_INCHES 1 // G20 (Do not alter value) // Modal Group G7: Cutter radius compensation mode -#define CUTTER_COMP_DISABLE 0 // G40 (Default: Must be zero) +#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) +#define CONTROL_MODE_EXACT_PATH 0 // G61 (Default: Must be zero) // Modal Group M7: Spindle control -#define SPINDLE_DISABLE 0 // M5 (Default: Must be zero) -#define SPINDLE_ENABLE_CW PL_COND_FLAG_SPINDLE_CW // M3 (NOTE: Uses planner condition bit flag) -#define SPINDLE_ENABLE_CCW PL_COND_FLAG_SPINDLE_CCW // M4 (NOTE: Uses planner condition bit flag) +#define SPINDLE_DISABLE 0 // M5 (Default: Must be zero) +#define SPINDLE_ENABLE_CW PL_COND_FLAG_SPINDLE_CW // M3 (NOTE: Uses planner condition bit flag) +#define SPINDLE_ENABLE_CCW PL_COND_FLAG_SPINDLE_CCW // M4 (NOTE: Uses planner condition bit flag) // Modal Group M8: Coolant control -#define COOLANT_DISABLE 0 // M9 (Default: Must be zero) -#define COOLANT_FLOOD_ENABLE PL_COND_FLAG_COOLANT_FLOOD // M8 (NOTE: Uses planner condition bit flag) -#define COOLANT_MIST_ENABLE PL_COND_FLAG_COOLANT_MIST // M7 (NOTE: Uses planner condition bit flag) +#define COOLANT_DISABLE 0 // M9 (Default: Must be zero) +#define COOLANT_FLOOD_ENABLE PL_COND_FLAG_COOLANT_FLOOD // M8 (NOTE: Uses planner condition bit flag) +#define COOLANT_MIST_ENABLE PL_COND_FLAG_COOLANT_MIST // M7 (NOTE: Uses planner condition bit flag) // Modal Group M9: Override control #ifdef DEACTIVATE_PARKING_UPON_INIT - #define OVERRIDE_DISABLED 0 // (Default: Must be zero) - #define OVERRIDE_PARKING_MOTION 1 // M56 +# define OVERRIDE_DISABLED 0 // (Default: Must be zero) +# define OVERRIDE_PARKING_MOTION 1 // M56 #else - #define OVERRIDE_PARKING_MOTION 0 // M56 (Default: Must be zero) - #define OVERRIDE_DISABLED 1 // Parking disabled. +# define OVERRIDE_PARKING_MOTION 0 // M56 (Default: Must be zero) +# define OVERRIDE_DISABLED 1 // Parking disabled. #endif // modal Group M10: User I/O control -#define NON_MODAL_IO_ENABLE 1 -#define NON_MODAL_IO_DISABLE 2 -#define MAX_USER_DIGITAL_PIN 4 +#define NON_MODAL_IO_ENABLE 1 +#define NON_MODAL_IO_DISABLE 2 +#define MAX_USER_DIGITAL_PIN 4 // Modal Group G8: Tool length offset -#define TOOL_LENGTH_OFFSET_CANCEL 0 // G49 (Default: Must be zero) -#define TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC 1 // G43.1 +#define TOOL_LENGTH_OFFSET_CANCEL 0 // G49 (Default: Must be zero) +#define TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC 1 // G43.1 #define TOOL_CHANGE 1 @@ -150,111 +150,107 @@ // N/A: Stores coordinate system value (54-59) to change to. // Define parameter word mapping. -#define WORD_F 0 -#define WORD_I 1 -#define WORD_J 2 -#define WORD_K 3 -#define WORD_L 4 -#define WORD_N 5 -#define WORD_P 6 -#define WORD_R 7 -#define WORD_S 8 -#define WORD_T 9 -#define WORD_X 10 -#define WORD_Y 11 -#define WORD_Z 12 -#define WORD_A 13 -#define WORD_B 14 -#define WORD_C 15 +#define WORD_F 0 +#define WORD_I 1 +#define WORD_J 2 +#define WORD_K 3 +#define WORD_L 4 +#define WORD_N 5 +#define WORD_P 6 +#define WORD_R 7 +#define WORD_S 8 +#define WORD_T 9 +#define WORD_X 10 +#define WORD_Y 11 +#define WORD_Z 12 +#define WORD_A 13 +#define WORD_B 14 +#define WORD_C 15 // Define g-code parser position updating flags -#define GC_UPDATE_POS_TARGET 0 // Must be zero -#define GC_UPDATE_POS_SYSTEM 1 -#define GC_UPDATE_POS_NONE 2 +#define GC_UPDATE_POS_TARGET 0 // Must be zero +#define GC_UPDATE_POS_SYSTEM 1 +#define GC_UPDATE_POS_NONE 2 // Define probe cycle exit states and assign proper position updating. -#define GC_PROBE_FOUND GC_UPDATE_POS_SYSTEM -#define GC_PROBE_ABORT GC_UPDATE_POS_NONE -#define GC_PROBE_FAIL_INIT GC_UPDATE_POS_NONE -#define GC_PROBE_FAIL_END GC_UPDATE_POS_TARGET +#define GC_PROBE_FOUND GC_UPDATE_POS_SYSTEM +#define GC_PROBE_ABORT GC_UPDATE_POS_NONE +#define GC_PROBE_FAIL_INIT GC_UPDATE_POS_NONE +#define GC_PROBE_FAIL_END GC_UPDATE_POS_TARGET #ifdef SET_CHECK_MODE_PROBE_TO_START - #define GC_PROBE_CHECK_MODE GC_UPDATE_POS_NONE +# define GC_PROBE_CHECK_MODE GC_UPDATE_POS_NONE #else - #define GC_PROBE_CHECK_MODE GC_UPDATE_POS_TARGET +# define GC_PROBE_CHECK_MODE GC_UPDATE_POS_TARGET #endif // Define gcode parser flags for handling special cases. -#define GC_PARSER_NONE 0 // Must be zero. -#define GC_PARSER_JOG_MOTION bit(0) -#define GC_PARSER_CHECK_MANTISSA bit(1) -#define GC_PARSER_ARC_IS_CLOCKWISE bit(2) -#define GC_PARSER_PROBE_IS_AWAY bit(3) -#define GC_PARSER_PROBE_IS_NO_ERROR bit(4) -#define GC_PARSER_LASER_FORCE_SYNC bit(5) -#define GC_PARSER_LASER_DISABLE bit(6) -#define GC_PARSER_LASER_ISMOTION bit(7) - +#define GC_PARSER_NONE 0 // Must be zero. +#define GC_PARSER_JOG_MOTION bit(0) +#define GC_PARSER_CHECK_MANTISSA bit(1) +#define GC_PARSER_ARC_IS_CLOCKWISE bit(2) +#define GC_PARSER_PROBE_IS_AWAY bit(3) +#define GC_PARSER_PROBE_IS_NO_ERROR bit(4) +#define GC_PARSER_LASER_FORCE_SYNC bit(5) +#define GC_PARSER_LASER_DISABLE bit(6) +#define GC_PARSER_LASER_ISMOTION bit(7) // NOTE: When this struct is zeroed, the above defines set the defaults for the system. typedef struct { - uint8_t motion; // {G0,G1,G2,G3,G38.2,G80} - uint8_t feed_rate; // {G93,G94} - uint8_t units; // {G20,G21} - uint8_t distance; // {G90,G91} + uint8_t motion; // {G0,G1,G2,G3,G38.2,G80} + uint8_t feed_rate; // {G93,G94} + uint8_t units; // {G20,G21} + uint8_t distance; // {G90,G91} // uint8_t distance_arc; // {G91.1} NOTE: Don't track. Only default supported. - uint8_t plane_select; // {G17,G18,G19} + uint8_t plane_select; // {G17,G18,G19} // uint8_t cutter_comp; // {G40} NOTE: Don't track. Only default supported. - uint8_t tool_length; // {G43.1,G49} - uint8_t coord_select; // {G54,G55,G56,G57,G58,G59} + uint8_t tool_length; // {G43.1,G49} + uint8_t coord_select; // {G54,G55,G56,G57,G58,G59} // uint8_t control; // {G61} NOTE: Don't track. Only default supported. - uint8_t program_flow; // {M0,M1,M2,M30} - uint8_t coolant; // {M7,M8,M9} - uint8_t spindle; // {M3,M4,M5} - uint8_t tool_change; // {M6} - uint8_t io_control; // {M62, M63} - uint8_t override; // {M56} + uint8_t program_flow; // {M0,M1,M2,M30} + uint8_t coolant; // {M7,M8,M9} + uint8_t spindle; // {M3,M4,M5} + uint8_t tool_change; // {M6} + uint8_t io_control; // {M62, M63} + uint8_t override; // {M56} } gc_modal_t; typedef struct { - float f; // Feed - float ijk[N_AXIS]; // I,J,K Axis arc offsets - uint8_t l; // G10 or canned cycles parameters - int32_t n; // Line number - float p; // G10 or dwell parameters + float f; // Feed + float ijk[N_AXIS]; // I,J,K Axis arc offsets + uint8_t l; // G10 or canned cycles parameters + int32_t n; // Line number + float p; // G10 or dwell parameters // float q; // G82 peck drilling - float r; // Arc radius - float s; // Spindle speed - uint8_t t; // Tool selection - float xyz[N_AXIS]; // X,Y,Z Translational axes + float r; // Arc radius + float s; // Spindle speed + uint8_t t; // Tool selection + float xyz[N_AXIS]; // X,Y,Z Translational axes } gc_values_t; - typedef struct { gc_modal_t modal; - float spindle_speed; // RPM - float feed_rate; // Millimeters/min - uint8_t tool; // Tracks tool number. NOT USED. - int32_t line_number; // Last line number sent + float spindle_speed; // RPM + float feed_rate; // Millimeters/min + uint8_t tool; // Tracks tool number. NOT USED. + int32_t line_number; // Last line number sent - float position[N_AXIS]; // Where the interpreter considers the tool to be at this point in the code + float position[N_AXIS]; // Where the interpreter considers the tool to be at this point in the code - float coord_system[N_AXIS]; // Current work coordinate system (G54+). Stores offset from absolute machine + float coord_system[N_AXIS]; // Current work coordinate system (G54+). Stores offset from absolute machine // position in mm. Loaded from EEPROM when called. - float coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to + float coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to // machine zero in mm. Non-persistent. Cleared upon reset and boot. - float tool_length_offset; // Tracks tool length offset value when enabled. + float tool_length_offset; // Tracks tool length offset value when enabled. } parser_state_t; extern parser_state_t gc_state; - typedef struct { - uint8_t non_modal_command; - gc_modal_t modal; + uint8_t non_modal_command; + gc_modal_t modal; gc_values_t values; } parser_block_t; - // Initialize the parser void gc_init(); diff --git a/Grbl_Esp32/grbl.h b/Grbl_Esp32/grbl.h index e0d26c76..56bdd0b4 100644 --- a/Grbl_Esp32/grbl.h +++ b/Grbl_Esp32/grbl.h @@ -25,7 +25,6 @@ #define GRBL_VERSION "1.3a" #define GRBL_VERSION_BUILD "20200727" - //#include #include #include @@ -52,7 +51,6 @@ #include "gcode.h" #include "grbl_limits.h" #include "motion_control.h" -#include "print.h" #include "probe.h" #include "protocol.h" #include "report.h" @@ -72,34 +70,34 @@ #include "grbl_sd.h" #ifdef ENABLE_BLUETOOTH - #include "BTconfig.h" +# include "BTconfig.h" #endif #ifdef ENABLE_WIFI - #include "wificonfig.h" - #ifdef ENABLE_HTTP - #include "serial2socket.h" - #endif - #ifdef ENABLE_TELNET - #include "telnet_server.h" - #endif - #ifdef ENABLE_NOTIFICATIONS - #include "notifications_service.h" - #endif +# include "wificonfig.h" +# ifdef ENABLE_HTTP +# include "serial2socket.h" +# endif +# ifdef ENABLE_TELNET +# include "telnet_server.h" +# endif +# ifdef ENABLE_NOTIFICATIONS +# include "notifications_service.h" +# endif #endif #include "solenoid_pen.h" #ifdef USE_SERVO_AXES - #include "servo_axis.h" +# include "servo_axis.h" #endif #ifdef USE_UNIPOLAR - #include "grbl_unipolar.h" +# include "grbl_unipolar.h" #endif #ifdef USE_I2S_OUT - #include "i2s_out.h" +# include "i2s_out.h" #endif // Called if USE_MACHINE_INIT is defined diff --git a/Grbl_Esp32/grbl_eeprom.cpp b/Grbl_Esp32/grbl_eeprom.cpp index 658fce07..07ddd7a9 100644 --- a/Grbl_Esp32/grbl_eeprom.cpp +++ b/Grbl_Esp32/grbl_eeprom.cpp @@ -34,7 +34,7 @@ void memcpy_to_eeprom_with_checksum(unsigned int destination, const char* source int memcpy_from_eeprom_with_checksum(char* destination, unsigned int source, unsigned int size) { unsigned char data, checksum = 0; for (; size > 0; size--) { - data = EEPROM.read(source++); + data = EEPROM.read(source++); checksum = (checksum << 1) || (checksum >> 7); checksum += data; *(destination++) = data; diff --git a/Grbl_Esp32/grbl_eeprom.h b/Grbl_Esp32/grbl_eeprom.h index 2e0fb7a8..d3786dcc 100644 --- a/Grbl_Esp32/grbl_eeprom.h +++ b/Grbl_Esp32/grbl_eeprom.h @@ -25,4 +25,4 @@ //unsigned char eeprom_get_char(unsigned int addr); //void eeprom_put_char(unsigned int addr, unsigned char new_value); void memcpy_to_eeprom_with_checksum(unsigned int destination, const char* source, unsigned int size); -int memcpy_from_eeprom_with_checksum(char* destination, unsigned int source, unsigned int size); +int memcpy_from_eeprom_with_checksum(char* destination, unsigned int source, unsigned int size); diff --git a/Grbl_Esp32/grbl_limits.cpp b/Grbl_Esp32/grbl_limits.cpp index abddc9ba..773c3cac 100644 --- a/Grbl_Esp32/grbl_limits.cpp +++ b/Grbl_Esp32/grbl_limits.cpp @@ -33,10 +33,10 @@ xQueueHandle limit_sw_queue; // used by limit switch debouncing // Homing axis search distance multiplier. Computed by this value times the cycle travel. #ifndef HOMING_AXIS_SEARCH_SCALAR - #define HOMING_AXIS_SEARCH_SCALAR 1.1 // Must be > 1 to ensure limit switch will be engaged. +# define HOMING_AXIS_SEARCH_SCALAR 1.1 // Must be > 1 to ensure limit switch will be engaged. #endif #ifndef HOMING_AXIS_LOCATE_SCALAR - #define HOMING_AXIS_LOCATE_SCALAR 5.0 // Must be > 1 to ensure limit switch is cleared. +# define HOMING_AXIS_LOCATE_SCALAR 5.0 // Must be > 1 to ensure limit switch is cleared. #endif void IRAM_ATTR isr_limit_switches() { @@ -52,16 +52,16 @@ void IRAM_ATTR isr_limit_switches() { int evt; xQueueSendFromISR(limit_sw_queue, &evt, NULL); #else -#ifdef HARD_LIMIT_FORCE_STATE_CHECK +# ifdef HARD_LIMIT_FORCE_STATE_CHECK // Check limit pin state. if (limits_get_state()) { - mc_reset(); // Initiate system kill. - system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event + mc_reset(); // Initiate system kill. + system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event } -#else - mc_reset(); // Initiate system kill. - system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event -#endif +# else + mc_reset(); // Initiate system kill. + system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event +# endif #endif } } @@ -75,10 +75,11 @@ void IRAM_ATTR isr_limit_switches() { // NOTE: Only the abort realtime command can interrupt this process. // TODO: Move limit pin-specific calls to a general function for portability. void limits_go_home(uint8_t cycle_mask) { - if (sys.abort) return; // Block if system reset has been issued. + if (sys.abort) + return; // Block if system reset has been issued. // Initialize plan data struct for homing motion. Spindle and coolant are disabled. - motors_set_homing_mode(cycle_mask, true); // tell motors homing is about to start - plan_line_data_t plan_data; + motors_set_homing_mode(cycle_mask, true); // tell motors homing is about to start + plan_line_data_t plan_data; plan_line_data_t* pl_data = &plan_data; memset(pl_data, 0, sizeof(plan_line_data_t)); pl_data->condition = (PL_COND_FLAG_SYSTEM_MOTION | PL_COND_FLAG_NO_FEED_OVERRIDE); @@ -88,28 +89,29 @@ void limits_go_home(uint8_t cycle_mask) { // Initialize variables used for homing computations. uint8_t n_cycle = (2 * n_homing_locate_cycle + 1); uint8_t step_pin[N_AXIS]; - float target[N_AXIS]; - float max_travel = 0.0; + float target[N_AXIS]; + float max_travel = 0.0; uint8_t idx; for (idx = 0; idx < N_AXIS; idx++) { // Initialize step pin masks step_pin[idx] = get_step_pin_mask(idx); #ifdef COREXY - if ((idx == A_MOTOR) || (idx == B_MOTOR)) step_pin[idx] = (get_step_pin_mask(X_AXIS) | get_step_pin_mask(Y_AXIS)); + if ((idx == A_MOTOR) || (idx == B_MOTOR)) + step_pin[idx] = (get_step_pin_mask(X_AXIS) | get_step_pin_mask(Y_AXIS)); #endif if (bit_istrue(cycle_mask, bit(idx))) { // Set target based on max_travel setting. Ensure homing switches engaged with search scalar. - max_travel = MAX(max_travel, (HOMING_AXIS_SEARCH_SCALAR) * axis_settings[idx]->max_travel->get()); + max_travel = MAX(max_travel, (HOMING_AXIS_SEARCH_SCALAR)*axis_settings[idx]->max_travel->get()); } } // Set search mode with approach at seek rate to quickly engage the specified cycle_mask limit switches. - bool approach = true; - float homing_rate = homing_seek_rate->get(); + bool approach = true; + float homing_rate = homing_seek_rate->get(); uint8_t limit_state, axislock, n_active_axis; do { system_convert_array_steps_to_mpos(target, sys_position); // Initialize and declare variables needed for homing routine. - axislock = 0; + axislock = 0; n_active_axis = 0; for (idx = 0; idx < N_AXIS; idx++) { // Set target location for active axes and setup computation for homing rate. @@ -132,24 +134,28 @@ void limits_go_home(uint8_t cycle_mask) { // NOTE: This happens to compile smaller than any other implementation tried. auto mask = homing_dir_mask->get(); if (bit_istrue(mask, bit(idx))) { - if (approach) target[idx] = -max_travel; - else target[idx] = max_travel; + if (approach) + target[idx] = -max_travel; + else + target[idx] = max_travel; } else { - if (approach) target[idx] = max_travel; - else target[idx] = -max_travel; + if (approach) + target[idx] = max_travel; + else + target[idx] = -max_travel; } // Apply axislock to the step port pins active in this cycle. axislock |= step_pin[idx]; } } - homing_rate *= sqrt(n_active_axis); // [sqrt(N_AXIS)] Adjust so individual axes all move at homing rate. + homing_rate *= sqrt(n_active_axis); // [sqrt(N_AXIS)] Adjust so individual axes all move at homing rate. sys.homing_axis_lock = axislock; // Perform homing cycle. Planner buffer should be empty, as required to initiate the homing cycle. - pl_data->feed_rate = homing_rate; // Set current homing rate. - plan_buffer_line(target, pl_data); // Bypass mc_line(). Directly plan homing motion. - sys.step_control = STEP_CONTROL_EXECUTE_SYS_MOTION; // Set to execute homing motion and clear existing flags. - st_prep_buffer(); // Prep and fill segment buffer from newly planned block. - st_wake_up(); // Initiate motion + pl_data->feed_rate = homing_rate; // Set current homing rate. + plan_buffer_line(target, pl_data); // Bypass mc_line(). Directly plan homing motion. + sys.step_control = STEP_CONTROL_EXECUTE_SYS_MOTION; // Set to execute homing motion and clear existing flags. + st_prep_buffer(); // Prep and fill segment buffer from newly planned block. + st_wake_up(); // Initiate motion do { if (approach) { // Check limit state. Lock out cycle axes when they change. @@ -158,8 +164,10 @@ void limits_go_home(uint8_t cycle_mask) { if (axislock & step_pin[idx]) { if (limit_state & bit(idx)) { #ifdef COREXY - if (idx == Z_AXIS) axislock &= ~(step_pin[Z_AXIS]); - else axislock &= ~(step_pin[A_MOTOR] | step_pin[B_MOTOR]); + if (idx == Z_AXIS) + axislock &= ~(step_pin[Z_AXIS]); + else + axislock &= ~(step_pin[A_MOTOR] | step_pin[B_MOTOR]); #else axislock &= ~(step_pin[idx]); #endif @@ -168,21 +176,25 @@ void limits_go_home(uint8_t cycle_mask) { } sys.homing_axis_lock = axislock; } - st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us. + st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us. // Exit routines: No time to run protocol_execute_realtime() in this loop. if (sys_rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET | EXEC_CYCLE_STOP)) { uint8_t rt_exec = sys_rt_exec_state; // Homing failure condition: Reset issued during cycle. - if (rt_exec & EXEC_RESET) system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_RESET); + if (rt_exec & EXEC_RESET) + system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_RESET); // Homing failure condition: Safety door was opened. - if (rt_exec & EXEC_SAFETY_DOOR) system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_DOOR); + if (rt_exec & EXEC_SAFETY_DOOR) + system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_DOOR); // Homing failure condition: Limit switch still engaged after pull-off motion - if (!approach && (limits_get_state() & cycle_mask)) system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_PULLOFF); + if (!approach && (limits_get_state() & cycle_mask)) + system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_PULLOFF); // Homing failure condition: Limit switch not found during approach. - if (approach && (rt_exec & EXEC_CYCLE_STOP)) system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_APPROACH); - if (sys_rt_exec_alarm) { - motors_set_homing_mode(cycle_mask, false); // tell motors homing is done...failed - mc_reset(); // Stop motors, if they are running. + if (approach && (rt_exec & EXEC_CYCLE_STOP)) + system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_APPROACH); + if (sys_rt_exec_alarm) { + motors_set_homing_mode(cycle_mask, false); // tell motors homing is done...failed + mc_reset(); // Stop motors, if they are running. protocol_execute_realtime(); return; } else { @@ -197,16 +209,16 @@ void limits_go_home(uint8_t cycle_mask) { delay_ms(I2S_OUT_DELAY_MS); } #endif - st_reset(); // Immediately force kill steppers and reset step segment buffer. - delay_ms(homing_debounce->get()); // Delay to allow transient dynamics to dissipate. + st_reset(); // Immediately force kill steppers and reset step segment buffer. + delay_ms(homing_debounce->get()); // Delay to allow transient dynamics to dissipate. // Reverse direction and reset homing rate for locate cycle(s). approach = !approach; // After first cycle, homing enters locating phase. Shorten search to pull-off distance. if (approach) { - max_travel = homing_pulloff->get() * HOMING_AXIS_LOCATE_SCALAR; + max_travel = homing_pulloff->get() * HOMING_AXIS_LOCATE_SCALAR; homing_rate = homing_feed_rate->get(); } else { - max_travel = homing_pulloff->get(); + max_travel = homing_pulloff->get(); homing_rate = homing_seek_rate->get(); } } while (n_cycle-- > 0); @@ -218,7 +230,7 @@ void limits_go_home(uint8_t cycle_mask) { // triggering when hard limits are enabled or when more than one axes shares a limit pin. int32_t set_axis_position; // Set machine positions for homed limit switches. Don't update non-homed axes. - auto mask = homing_dir_mask->get(); + auto mask = homing_dir_mask->get(); auto pulloff = homing_pulloff->get(); for (idx = 0; idx < N_AXIS; idx++) { auto steps = axis_settings[idx]->steps_per_mm->get(); @@ -228,28 +240,28 @@ void limits_go_home(uint8_t cycle_mask) { #else auto travel = axis_settings[idx]->max_travel->get(); if (bit_istrue(mask, bit(idx))) { -#ifdef HOMING_FORCE_POSITIVE_SPACE - set_axis_position = 0; //lround(settings.homing_pulloff*settings.steps_per_mm[idx]); -#else +# ifdef HOMING_FORCE_POSITIVE_SPACE + set_axis_position = 0; //lround(settings.homing_pulloff*settings.steps_per_mm[idx]); +# else set_axis_position = lround((-travel + pulloff) * steps); -#endif +# endif } else { -#ifdef HOMING_FORCE_POSITIVE_SPACE +# ifdef HOMING_FORCE_POSITIVE_SPACE set_axis_position = lround((-travel - pulloff) * steps); -#else +# else set_axis_position = lround(-pulloff * steps); -#endif +# endif } #endif #ifdef COREXY if (idx == X_AXIS) { int32_t off_axis_position = system_convert_corexy_to_y_axis_steps(sys_position); - sys_position[A_MOTOR] = set_axis_position + off_axis_position; - sys_position[B_MOTOR] = set_axis_position - off_axis_position; + sys_position[A_MOTOR] = set_axis_position + off_axis_position; + sys_position[B_MOTOR] = set_axis_position - off_axis_position; } else if (idx == Y_AXIS) { int32_t off_axis_position = system_convert_corexy_to_x_axis_steps(sys_position); - sys_position[A_MOTOR] = off_axis_position + set_axis_position; - sys_position[B_MOTOR] = off_axis_position - set_axis_position; + sys_position[A_MOTOR] = off_axis_position + set_axis_position; + sys_position[B_MOTOR] = off_axis_position - set_axis_position; } else sys_position[idx] = set_axis_position; #else @@ -257,28 +269,23 @@ void limits_go_home(uint8_t cycle_mask) { #endif } } - sys.step_control = STEP_CONTROL_NORMAL_OP; // Return step control to normal operation. - motors_set_homing_mode(cycle_mask, false); // tell motors homing is done + sys.step_control = STEP_CONTROL_NORMAL_OP; // Return step control to normal operation. + motors_set_homing_mode(cycle_mask, false); // tell motors homing is done } uint8_t limit_pins[] = { - X_LIMIT_PIN, - Y_LIMIT_PIN, - Z_LIMIT_PIN, - A_LIMIT_PIN, - B_LIMIT_PIN, - C_LIMIT_PIN, + X_LIMIT_PIN, Y_LIMIT_PIN, Z_LIMIT_PIN, A_LIMIT_PIN, B_LIMIT_PIN, C_LIMIT_PIN, }; uint8_t limit_mask = 0; void limits_init() { limit_mask = 0; - int mode = INPUT_PULLUP; + int mode = INPUT_PULLUP; #ifdef DISABLE_LIMIT_PIN_PULL_UP mode = INPUT; #endif - for (int i=0; iget()) { @@ -338,11 +345,11 @@ void limits_soft_check(float* target) { if (system_check_travel_limits(target)) { // TODO for debugging only 3 axes right now grbl_msg_sendf(CLIENT_SERIAL, - MSG_LEVEL_INFO, - "Soft limit error target WPOS X:%5.2f Y:%5.2f Z:%5.2f", - target[X_AXIS] - gc_state.coord_system[X_AXIS], - target[Y_AXIS] - gc_state.coord_system[Y_AXIS], - target[Z_AXIS] - gc_state.coord_system[Z_AXIS]); + MSG_LEVEL_INFO, + "Soft limit error target WPOS X:%5.2f Y:%5.2f Z:%5.2f", + target[X_AXIS] - gc_state.coord_system[X_AXIS], + target[Y_AXIS] - gc_state.coord_system[Y_AXIS], + target[Z_AXIS] - gc_state.coord_system[Z_AXIS]); sys.soft_limit = true; // Force feed hold if cycle is active. All buffered blocks are guaranteed to be within @@ -352,12 +359,13 @@ void limits_soft_check(float* target) { system_set_exec_state_flag(EXEC_FEED_HOLD); do { protocol_execute_realtime(); - if (sys.abort) return; + if (sys.abort) + return; } while (sys.state != STATE_IDLE); } - mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown. - system_set_exec_alarm(EXEC_ALARM_SOFT_LIMIT); // Indicate soft limit critical event - protocol_execute_realtime(); // Execute to enter critical event loop and system abort + mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown. + system_set_exec_alarm(EXEC_ALARM_SOFT_LIMIT); // Indicate soft limit critical event + protocol_execute_realtime(); // Execute to enter critical event loop and system abort return; } } @@ -366,14 +374,14 @@ void limits_soft_check(float* target) { void limitCheckTask(void* pvParameters) { while (true) { int evt; - xQueueReceive(limit_sw_queue, &evt, portMAX_DELAY); // block until receive queue - vTaskDelay(DEBOUNCE_PERIOD / portTICK_PERIOD_MS); // delay a while + xQueueReceive(limit_sw_queue, &evt, portMAX_DELAY); // block until receive queue + vTaskDelay(DEBOUNCE_PERIOD / portTICK_PERIOD_MS); // delay a while uint8_t switch_state; switch_state = limits_get_state(); if (switch_state) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Limit Switch State %08d", switch_state); - mc_reset(); // Initiate system kill. - system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event + mc_reset(); // Initiate system kill. + system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); // Indicate hard limit critical event } } } @@ -398,17 +406,17 @@ bool axis_is_squared(uint8_t axis_mask) { return true; #endif } - if (axis_mask == (1 << A_AXIS)) { + if (axis_mask == (1 << A_AXIS)) { #ifdef A_AXIS_SQUARING return true; #endif } - if (axis_mask == (1 << B_AXIS)) { + if (axis_mask == (1 << B_AXIS)) { #ifdef B_AXIS_SQUARING return true; #endif } - if (axis_mask == (1 << C_AXIS)) { + if (axis_mask == (1 << C_AXIS)) { #ifdef C_AXIS_SQUARING return true; #endif diff --git a/Grbl_Esp32/grbl_limits.h b/Grbl_Esp32/grbl_limits.h index dd62db11..65e68af4 100644 --- a/Grbl_Esp32/grbl_limits.h +++ b/Grbl_Esp32/grbl_limits.h @@ -29,9 +29,9 @@ extern uint8_t n_homing_locate_cycle; -#define SQUARING_MODE_DUAL 0 // both motors run -#define SQUARING_MODE_A 1 // A motor runs -#define SQUARING_MODE_B 2 // B motor runs +#define SQUARING_MODE_DUAL 0 // both motors run +#define SQUARING_MODE_A 1 // A motor runs +#define SQUARING_MODE_B 2 // B motor runs // Initialize the limits module void limits_init(); diff --git a/Grbl_Esp32/grbl_sd.cpp b/Grbl_Esp32/grbl_sd.cpp index 0b0a9bc8..1dc143d3 100644 --- a/Grbl_Esp32/grbl_sd.cpp +++ b/Grbl_Esp32/grbl_sd.cpp @@ -20,11 +20,11 @@ #include "grbl_sd.h" -File myFile; -bool SD_ready_next = false; // Grbl has processed a line and is waiting for another -uint8_t SD_client = CLIENT_SERIAL; -uint32_t sd_current_line_number; // stores the most recent line number read from the SD -static char comment[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated. +File myFile; +bool SD_ready_next = false; // Grbl has processed a line and is waiting for another +uint8_t SD_client = CLIENT_SERIAL; +uint32_t sd_current_line_number; // stores the most recent line number read from the SD +static char comment[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated. // attempt to mount the SD card /*bool sd_mount() @@ -65,7 +65,7 @@ boolean openFile(fs::FS& fs, const char* path) { return false; } set_sd_state(SDCARD_BUSY_PRINTING); - SD_ready_next = false; // this will get set to true when Grbl issues "ok" message + SD_ready_next = false; // this will get set to true when Grbl issues "ok" message sd_current_line_number = 0; return true; } @@ -74,7 +74,7 @@ boolean closeFile() { if (!myFile) return false; set_sd_state(SDCARD_IDLE); - SD_ready_next = false; + SD_ready_next = false; sd_current_line_number = 0; myFile.close(); return true; @@ -119,7 +119,6 @@ uint32_t sd_get_current_line_number() { return sd_current_line_number; } - uint8_t sd_state = SDCARD_IDLE; uint8_t get_sd_state(bool refresh) { @@ -142,13 +141,14 @@ uint8_t get_sd_state(bool refresh) { //using default value for speed ? should be parameter //refresh content if card was removed if (SD.begin((GRBL_SPI_SS == -1) ? SS : GRBL_SPI_SS, SPI, GRBL_SPI_FREQ)) { - if (SD.cardSize() > 0)sd_state = SDCARD_IDLE; + if (SD.cardSize() > 0) + sd_state = SDCARD_IDLE; } return sd_state; } uint8_t set_sd_state(uint8_t flag) { - sd_state = flag; + sd_state = flag; return sd_state; } @@ -158,5 +158,3 @@ void sd_get_current_filename(char* name) { else name[0] = 0; } - - diff --git a/Grbl_Esp32/grbl_sd.h b/Grbl_Esp32/grbl_sd.h index 68d5de3d..2b7b6b27 100644 --- a/Grbl_Esp32/grbl_sd.h +++ b/Grbl_Esp32/grbl_sd.h @@ -20,7 +20,7 @@ #include "SD.h" #include "SPI.h" -#define FILE_TYPE_COUNT 5 // number of acceptable gcode file types in array +#define FILE_TYPE_COUNT 5 // number of acceptable gcode file types in array #define SDCARD_DET_PIN -1 #define SDCARD_DET_VAL 0 @@ -31,19 +31,17 @@ #define SDCARD_BUSY_UPLOADING 4 #define SDCARD_BUSY_PARSING 8 - - -extern bool SD_ready_next; // Grbl has processed a line and is waiting for another -extern uint8_t SD_client; +extern bool SD_ready_next; // Grbl has processed a line and is waiting for another +extern uint8_t SD_client; //bool sd_mount(); -uint8_t get_sd_state(bool refresh); -uint8_t set_sd_state(uint8_t flag); -void listDir(fs::FS& fs, const char* dirname, uint8_t levels, uint8_t client); -boolean openFile(fs::FS& fs, const char* path); -boolean closeFile(); -boolean readFileLine(char* line, int len); -void readFile(fs::FS& fs, const char* path); -float sd_report_perc_complete(); +uint8_t get_sd_state(bool refresh); +uint8_t set_sd_state(uint8_t flag); +void listDir(fs::FS& fs, const char* dirname, uint8_t levels, uint8_t client); +boolean openFile(fs::FS& fs, const char* path); +boolean closeFile(); +boolean readFileLine(char* line, int len); +void readFile(fs::FS& fs, const char* path); +float sd_report_perc_complete(); uint32_t sd_get_current_line_number(); -void sd_get_current_filename(char* name); +void sd_get_current_filename(char* name); diff --git a/Grbl_Esp32/i2s_out.cpp b/Grbl_Esp32/i2s_out.cpp index 11d88d07..0ddbba61 100644 --- a/Grbl_Esp32/i2s_out.cpp +++ b/Grbl_Esp32/i2s_out.cpp @@ -44,16 +44,16 @@ #ifdef USE_I2S_OUT -#include -#include -#include -#include -#include +# include +# include +# include +# include +# include -#include +# include -#include "Pins.h" -#include "i2s_out.h" +# include "Pins.h" +# include "i2s_out.h" // // Configrations for DMA connected I2S @@ -71,597 +71,597 @@ // Reference information: // FreeRTOS task time slice = portTICK_PERIOD_MS = 1 ms (ESP32 FreeRTOS port) // -#define I2S_SAMPLE_SIZE 4 /* 4 bytes, 32 bits per sample */ -#define DMA_SAMPLE_COUNT I2S_OUT_DMABUF_LEN / I2S_SAMPLE_SIZE /* number of samples per buffer */ -#define SAMPLE_SAFE_COUNT (20/I2S_OUT_USEC_PER_PULSE) /* prevent buffer overrun (GRBL's $0 should be less than or equal 20) */ +# define I2S_SAMPLE_SIZE 4 /* 4 bytes, 32 bits per sample */ +# define DMA_SAMPLE_COUNT I2S_OUT_DMABUF_LEN / I2S_SAMPLE_SIZE /* number of samples per buffer */ +# define SAMPLE_SAFE_COUNT (20 / I2S_OUT_USEC_PER_PULSE) /* prevent buffer overrun (GRBL's $0 should be less than or equal 20) */ -#ifdef USE_I2S_OUT_STREAM +# ifdef USE_I2S_OUT_STREAM typedef struct { - uint32_t **buffers; - uint32_t *current; - uint32_t rw_pos; - lldesc_t **desc; - xQueueHandle queue; + uint32_t** buffers; + uint32_t* current; + uint32_t rw_pos; + lldesc_t** desc; + xQueueHandle queue; } i2s_out_dma_t; static i2s_out_dma_t o_dma; static intr_handle_t i2s_out_isr_handle; -#endif +# endif // output value static atomic_uint_least32_t i2s_out_port_data = ATOMIC_VAR_INIT(0); // inner lock static portMUX_TYPE i2s_out_spinlock = portMUX_INITIALIZER_UNLOCKED; -#define I2S_OUT_ENTER_CRITICAL() portENTER_CRITICAL(&i2s_out_spinlock) -#define I2S_OUT_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_out_spinlock) -#define I2S_OUT_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_out_spinlock) -#define I2S_OUT_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_out_spinlock) +# define I2S_OUT_ENTER_CRITICAL() portENTER_CRITICAL(&i2s_out_spinlock) +# define I2S_OUT_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_out_spinlock) +# define I2S_OUT_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_out_spinlock) +# define I2S_OUT_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_out_spinlock) static int i2s_out_initialized = 0; -#ifdef USE_I2S_OUT_STREAM -static volatile uint32_t i2s_out_pulse_period; -static uint32_t i2s_out_remain_time_until_next_pulse; // Time remaining until the next pulse (μsec) +# ifdef USE_I2S_OUT_STREAM +static volatile uint32_t i2s_out_pulse_period; +static uint32_t i2s_out_remain_time_until_next_pulse; // Time remaining until the next pulse (μsec) static volatile i2s_out_pulse_func_t i2s_out_pulse_func; -#endif +# endif -static uint8_t i2s_out_ws_pin = 255; -static uint8_t i2s_out_bck_pin = 255; +static uint8_t i2s_out_ws_pin = 255; +static uint8_t i2s_out_bck_pin = 255; static uint8_t i2s_out_data_pin = 255; enum i2s_out_pulser_status_t { - PASSTHROUGH = 0, // Static I2S mode.The i2s_out_write() reflected with very little delay - STEPPING, // Streaming step data. - WAITING, // Waiting for the step DMA completion + PASSTHROUGH = 0, // Static I2S mode.The i2s_out_write() reflected with very little delay + STEPPING, // Streaming step data. + WAITING, // Waiting for the step DMA completion }; static volatile i2s_out_pulser_status_t i2s_out_pulser_status = PASSTHROUGH; // outer lock static portMUX_TYPE i2s_out_pulser_spinlock = portMUX_INITIALIZER_UNLOCKED; -#define I2S_OUT_PULSER_ENTER_CRITICAL() portENTER_CRITICAL(&i2s_out_pulser_spinlock) -#define I2S_OUT_PULSER_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_out_pulser_spinlock) -#define I2S_OUT_PULSER_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_out_pulser_spinlock) -#define I2S_OUT_PULSER_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_out_pulser_spinlock) +# define I2S_OUT_PULSER_ENTER_CRITICAL() portENTER_CRITICAL(&i2s_out_pulser_spinlock) +# define I2S_OUT_PULSER_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_out_pulser_spinlock) +# define I2S_OUT_PULSER_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_out_pulser_spinlock) +# define I2S_OUT_PULSER_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_out_pulser_spinlock) // // Internal functions // static inline void gpio_matrix_out_check(uint8_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) { - //if pin == 255, do not need to configure - if (gpio != 255) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO); - gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT); - gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv); - } + //if pin == 255, do not need to configure + if (gpio != 255) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO); + gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT); + gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv); + } } static inline void i2s_out_single_data() { -#if I2S_OUT_NUM_BITS == 16 - uint32_t port_data = atomic_load(&i2s_out_port_data); - port_data <<= 16; // Shift needed. This specification is not spelled out in the manual. - I2S0.conf_single_data = port_data; // Apply port data in real-time (static I2S) -#else - I2S0.conf_single_data = atomic_load(&i2s_out_port_data); // Apply port data in real-time (static I2S) -#endif +# if I2S_OUT_NUM_BITS == 16 + uint32_t port_data = atomic_load(&i2s_out_port_data); + port_data <<= 16; // Shift needed. This specification is not spelled out in the manual. + I2S0.conf_single_data = port_data; // Apply port data in real-time (static I2S) +# else + I2S0.conf_single_data = atomic_load(&i2s_out_port_data); // Apply port data in real-time (static I2S) +# endif } static inline void i2s_out_reset_fifo_without_lock() { - I2S0.conf.rx_fifo_reset = 1; - I2S0.conf.rx_fifo_reset = 0; - I2S0.conf.tx_fifo_reset = 1; - I2S0.conf.tx_fifo_reset = 0; + I2S0.conf.rx_fifo_reset = 1; + I2S0.conf.rx_fifo_reset = 0; + I2S0.conf.tx_fifo_reset = 1; + I2S0.conf.tx_fifo_reset = 0; } static void IRAM_ATTR i2s_out_reset_fifo() { - I2S_OUT_ENTER_CRITICAL(); - i2s_out_reset_fifo_without_lock(); - I2S_OUT_EXIT_CRITICAL(); + I2S_OUT_ENTER_CRITICAL(); + i2s_out_reset_fifo_without_lock(); + I2S_OUT_EXIT_CRITICAL(); } -#ifdef USE_I2S_OUT_STREAM -static int IRAM_ATTR i2s_clear_dma_buffer(lldesc_t *dma_desc, uint32_t port_data) { - - uint32_t *buf = (uint32_t*)dma_desc->buf; - for (int i = 0; i < DMA_SAMPLE_COUNT; i++) { - buf[i] = port_data; - } - // Restore the buffer length. - // The length may have been changed short when the data was filled in to prevent buffer overrun. - dma_desc->length = I2S_OUT_DMABUF_LEN; - return 0; +# ifdef USE_I2S_OUT_STREAM +static int IRAM_ATTR i2s_clear_dma_buffer(lldesc_t* dma_desc, uint32_t port_data) { + uint32_t* buf = (uint32_t*)dma_desc->buf; + for (int i = 0; i < DMA_SAMPLE_COUNT; i++) { + buf[i] = port_data; + } + // Restore the buffer length. + // The length may have been changed short when the data was filled in to prevent buffer overrun. + dma_desc->length = I2S_OUT_DMABUF_LEN; + return 0; } static int IRAM_ATTR i2s_clear_o_dma_buffers(uint32_t port_data) { - for (int buf_idx = 0; buf_idx < I2S_OUT_DMABUF_COUNT; buf_idx++) { - // Initialize DMA descriptor - o_dma.desc[buf_idx]->owner = 1; - o_dma.desc[buf_idx]->eof = 1; // set to 1 will trigger the interrupt - o_dma.desc[buf_idx]->sosf = 0; - o_dma.desc[buf_idx]->length = I2S_OUT_DMABUF_LEN; - o_dma.desc[buf_idx]->size = I2S_OUT_DMABUF_LEN; - o_dma.desc[buf_idx]->buf = (uint8_t *) o_dma.buffers[buf_idx]; - o_dma.desc[buf_idx]->offset = 0; - o_dma.desc[buf_idx]->qe.stqe_next = (lldesc_t *)((buf_idx < (I2S_OUT_DMABUF_COUNT - 1)) ? (o_dma.desc[buf_idx + 1]) : o_dma.desc[0]); - i2s_clear_dma_buffer(o_dma.desc[buf_idx], port_data); - } - return 0; + for (int buf_idx = 0; buf_idx < I2S_OUT_DMABUF_COUNT; buf_idx++) { + // Initialize DMA descriptor + o_dma.desc[buf_idx]->owner = 1; + o_dma.desc[buf_idx]->eof = 1; // set to 1 will trigger the interrupt + o_dma.desc[buf_idx]->sosf = 0; + o_dma.desc[buf_idx]->length = I2S_OUT_DMABUF_LEN; + o_dma.desc[buf_idx]->size = I2S_OUT_DMABUF_LEN; + o_dma.desc[buf_idx]->buf = (uint8_t*)o_dma.buffers[buf_idx]; + o_dma.desc[buf_idx]->offset = 0; + o_dma.desc[buf_idx]->qe.stqe_next = (lldesc_t*)((buf_idx < (I2S_OUT_DMABUF_COUNT - 1)) ? (o_dma.desc[buf_idx + 1]) : o_dma.desc[0]); + i2s_clear_dma_buffer(o_dma.desc[buf_idx], port_data); + } + return 0; } -#endif +# endif static int IRAM_ATTR i2s_out_gpio_attach(uint8_t ws, uint8_t bck, uint8_t data) { - // Route the i2s pins to the appropriate GPIO - gpio_matrix_out_check(data, I2S0O_DATA_OUT23_IDX, 0, 0); - gpio_matrix_out_check(bck, I2S0O_BCK_OUT_IDX, 0, 0); - gpio_matrix_out_check(ws, I2S0O_WS_OUT_IDX, 0, 0); - return 0; + // Route the i2s pins to the appropriate GPIO + gpio_matrix_out_check(data, I2S0O_DATA_OUT23_IDX, 0, 0); + gpio_matrix_out_check(bck, I2S0O_BCK_OUT_IDX, 0, 0); + gpio_matrix_out_check(ws, I2S0O_WS_OUT_IDX, 0, 0); + return 0; } -#define I2S_OUT_DETACH_PORT_IDX 0x100 +# define I2S_OUT_DETACH_PORT_IDX 0x100 static int IRAM_ATTR i2s_out_gpio_detach(uint8_t ws, uint8_t bck, uint8_t data) { - // Route the i2s pins to the appropriate GPIO - gpio_matrix_out_check(ws, I2S_OUT_DETACH_PORT_IDX, 0, 0); - gpio_matrix_out_check(bck, I2S_OUT_DETACH_PORT_IDX, 0, 0); - gpio_matrix_out_check(data, I2S_OUT_DETACH_PORT_IDX, 0, 0); - return 0; + // Route the i2s pins to the appropriate GPIO + gpio_matrix_out_check(ws, I2S_OUT_DETACH_PORT_IDX, 0, 0); + gpio_matrix_out_check(bck, I2S_OUT_DETACH_PORT_IDX, 0, 0); + gpio_matrix_out_check(data, I2S_OUT_DETACH_PORT_IDX, 0, 0); + return 0; } static int IRAM_ATTR i2s_out_gpio_shiftout(uint32_t port_data) { - __digitalWrite(i2s_out_ws_pin, LOW); - for (int i = 0; i buf; - o_dma.rw_pos = 0; - // It reuses the oldest (just transferred) buffer with the name "current" - // and fills the buffer for later DMA. - I2S_OUT_PULSER_ENTER_CRITICAL(); // Lock pulser status - if (i2s_out_pulser_status == STEPPING) { - // - // Fillout the buffer for pulse - // - // To avoid buffer overflow, all of the maximum pulse width (normaly about 10us) - // is adjusted to be in a single buffer. - // DMA_SAMPLE_SAFE_COUNT is referred to as the margin value. - // Therefore, if a buffer is close to full and it is time to generate a pulse, - // the generation of the buffer is interrupted (the buffer length is shortened slightly) - // and the pulse generation is postponed until the next buffer is filled. - // - o_dma.rw_pos = 0; - while (o_dma.rw_pos < (DMA_SAMPLE_COUNT - SAMPLE_SAFE_COUNT)) { - // no data to read (buffer empty) - if (i2s_out_remain_time_until_next_pulse < I2S_OUT_USEC_PER_PULSE) { - // pulser status may change in pulse phase func, so I need to check it every time. - if (i2s_out_pulser_status == STEPPING) { - // fillout future DMA buffer (tail of the DMA buffer chains) - if (i2s_out_pulse_func != NULL) { - I2S_OUT_PULSER_EXIT_CRITICAL(); // Temporarily unlocked status lock as it may be locked in pulse callback. - (*i2s_out_pulse_func)(); // should be pushed into buffer max DMA_SAMPLE_SAFE_COUNT - I2S_OUT_PULSER_ENTER_CRITICAL(); // Lock again. - i2s_out_remain_time_until_next_pulse = i2s_out_pulse_period; - if (i2s_out_pulser_status == WAITING) { - // i2s_out_set_passthrough() has called from the pulse function. - // It needs to go into pass-through mode. - // This DMA descriptor must be a tail of the chain. - dma_desc->qe.stqe_next = NULL; // Cut the DMA descriptor ring. This allow us to identify the tail of the buffer. - } else if (i2s_out_pulser_status == PASSTHROUGH) { - // i2s_out_reset() has called during the execution of the pulse function. - // I2S has already in static mode, and buffers has cleared to zero. - // To prevent the pulse function from being called back, - // we assume that the buffer is already full. - i2s_out_remain_time_until_next_pulse = 0; // There is no need to fill the current buffer. - o_dma.rw_pos = DMA_SAMPLE_COUNT; // The buffer is full. - break; - } - continue; +static int IRAM_ATTR i2s_fillout_dma_buffer(lldesc_t* dma_desc) { + uint32_t* buf = (uint32_t*)dma_desc->buf; + o_dma.rw_pos = 0; + // It reuses the oldest (just transferred) buffer with the name "current" + // and fills the buffer for later DMA. + I2S_OUT_PULSER_ENTER_CRITICAL(); // Lock pulser status + if (i2s_out_pulser_status == STEPPING) { + // + // Fillout the buffer for pulse + // + // To avoid buffer overflow, all of the maximum pulse width (normaly about 10us) + // is adjusted to be in a single buffer. + // DMA_SAMPLE_SAFE_COUNT is referred to as the margin value. + // Therefore, if a buffer is close to full and it is time to generate a pulse, + // the generation of the buffer is interrupted (the buffer length is shortened slightly) + // and the pulse generation is postponed until the next buffer is filled. + // + o_dma.rw_pos = 0; + while (o_dma.rw_pos < (DMA_SAMPLE_COUNT - SAMPLE_SAFE_COUNT)) { + // no data to read (buffer empty) + if (i2s_out_remain_time_until_next_pulse < I2S_OUT_USEC_PER_PULSE) { + // pulser status may change in pulse phase func, so I need to check it every time. + if (i2s_out_pulser_status == STEPPING) { + // fillout future DMA buffer (tail of the DMA buffer chains) + if (i2s_out_pulse_func != NULL) { + I2S_OUT_PULSER_EXIT_CRITICAL(); // Temporarily unlocked status lock as it may be locked in pulse callback. + (*i2s_out_pulse_func)(); // should be pushed into buffer max DMA_SAMPLE_SAFE_COUNT + I2S_OUT_PULSER_ENTER_CRITICAL(); // Lock again. + i2s_out_remain_time_until_next_pulse = i2s_out_pulse_period; + if (i2s_out_pulser_status == WAITING) { + // i2s_out_set_passthrough() has called from the pulse function. + // It needs to go into pass-through mode. + // This DMA descriptor must be a tail of the chain. + dma_desc->qe.stqe_next = NULL; // Cut the DMA descriptor ring. This allow us to identify the tail of the buffer. + } else if (i2s_out_pulser_status == PASSTHROUGH) { + // i2s_out_reset() has called during the execution of the pulse function. + // I2S has already in static mode, and buffers has cleared to zero. + // To prevent the pulse function from being called back, + // we assume that the buffer is already full. + i2s_out_remain_time_until_next_pulse = 0; // There is no need to fill the current buffer. + o_dma.rw_pos = DMA_SAMPLE_COUNT; // The buffer is full. + break; + } + continue; + } + } + } + // no pulse data in push buffer (pulse off or idle or callback is not defined) + buf[o_dma.rw_pos++] = atomic_load(&i2s_out_port_data); + if (i2s_out_remain_time_until_next_pulse >= I2S_OUT_USEC_PER_PULSE) { + i2s_out_remain_time_until_next_pulse -= I2S_OUT_USEC_PER_PULSE; + } else { + i2s_out_remain_time_until_next_pulse = 0; } - } - } - // no pulse data in push buffer (pulse off or idle or callback is not defined) - buf[o_dma.rw_pos++] = atomic_load(&i2s_out_port_data); - if (i2s_out_remain_time_until_next_pulse >= I2S_OUT_USEC_PER_PULSE) { - i2s_out_remain_time_until_next_pulse -= I2S_OUT_USEC_PER_PULSE; - } else { - i2s_out_remain_time_until_next_pulse = 0; } + // set filled length to the DMA descriptor + dma_desc->length = o_dma.rw_pos * I2S_SAMPLE_SIZE; + } else if (i2s_out_pulser_status == WAITING) { + i2s_clear_dma_buffer(dma_desc, 0); // Essentially, no clearing is required. I'll make sure I know when I've written something. + o_dma.rw_pos = 0; // If someone calls i2s_out_push_sample, make sure there is no buffer overflow + dma_desc->qe.stqe_next = NULL; // Cut the DMA descriptor ring. This allow us to identify the tail of the buffer. + } else { + // Stepper paused (passthrough state, static I2S control mode) + // In the passthrough mode, there is no need to fill the buffer with port_data. + i2s_clear_dma_buffer(dma_desc, 0); // Essentially, no clearing is required. I'll make sure I know when I've written something. + o_dma.rw_pos = 0; // If someone calls i2s_out_push_sample, make sure there is no buffer overflow } - // set filled length to the DMA descriptor - dma_desc->length = o_dma.rw_pos * I2S_SAMPLE_SIZE; - } else if (i2s_out_pulser_status == WAITING) { - i2s_clear_dma_buffer(dma_desc, 0); // Essentially, no clearing is required. I'll make sure I know when I've written something. - o_dma.rw_pos = 0; // If someone calls i2s_out_push_sample, make sure there is no buffer overflow - dma_desc->qe.stqe_next = NULL; // Cut the DMA descriptor ring. This allow us to identify the tail of the buffer. - } else { - // Stepper paused (passthrough state, static I2S control mode) - // In the passthrough mode, there is no need to fill the buffer with port_data. - i2s_clear_dma_buffer(dma_desc, 0); // Essentially, no clearing is required. I'll make sure I know when I've written something. - o_dma.rw_pos = 0; // If someone calls i2s_out_push_sample, make sure there is no buffer overflow - } - I2S_OUT_PULSER_EXIT_CRITICAL(); // Unlock pulser status + I2S_OUT_PULSER_EXIT_CRITICAL(); // Unlock pulser status - return 0; + return 0; } // // I2S out DMA Interrupts handler // -static void IRAM_ATTR i2s_out_intr_handler(void *arg) { - lldesc_t *finish_desc; - portBASE_TYPE high_priority_task_awoken = pdFALSE; +static void IRAM_ATTR i2s_out_intr_handler(void* arg) { + lldesc_t* finish_desc; + portBASE_TYPE high_priority_task_awoken = pdFALSE; - if (I2S0.int_st.out_eof || I2S0.int_st.out_total_eof) { - if (I2S0.int_st.out_total_eof) { - // This is tail of the DMA descriptors - I2S_OUT_ENTER_CRITICAL_ISR(); - // Stop FIFO DMA - I2S0.out_link.stop = 1; - // Disconnect DMA from FIFO - I2S0.fifo_conf.dscr_en = 0; //Unset this bit to disable I2S DMA mode. (R/W) - // Stop TX module - I2S0.conf.tx_start = 0; - I2S_OUT_EXIT_CRITICAL_ISR(); - } - // Get the descriptor of the last item in the linkedlist - finish_desc = (lldesc_t*) I2S0.out_eof_des_addr; + if (I2S0.int_st.out_eof || I2S0.int_st.out_total_eof) { + if (I2S0.int_st.out_total_eof) { + // This is tail of the DMA descriptors + I2S_OUT_ENTER_CRITICAL_ISR(); + // Stop FIFO DMA + I2S0.out_link.stop = 1; + // Disconnect DMA from FIFO + I2S0.fifo_conf.dscr_en = 0; //Unset this bit to disable I2S DMA mode. (R/W) + // Stop TX module + I2S0.conf.tx_start = 0; + I2S_OUT_EXIT_CRITICAL_ISR(); + } + // Get the descriptor of the last item in the linkedlist + finish_desc = (lldesc_t*)I2S0.out_eof_des_addr; - // If the queue is full it's because we have an underflow, - // more than buf_count isr without new data, remove the front buffer - if (xQueueIsQueueFullFromISR(o_dma.queue)) { - lldesc_t *front_desc; - // Remove a descriptor from the DMA complete event queue - xQueueReceiveFromISR(o_dma.queue, &front_desc, &high_priority_task_awoken); - I2S_OUT_PULSER_ENTER_CRITICAL_ISR(); - uint32_t port_data = 0; - if (i2s_out_pulser_status == STEPPING) { - port_data = atomic_load(&i2s_out_port_data); - } - I2S_OUT_PULSER_EXIT_CRITICAL_ISR(); - for (int i = 0; i < DMA_SAMPLE_COUNT; i++) { - front_desc->buf[i] = port_data; - } - front_desc->length = I2S_OUT_DMABUF_LEN; + // If the queue is full it's because we have an underflow, + // more than buf_count isr without new data, remove the front buffer + if (xQueueIsQueueFullFromISR(o_dma.queue)) { + lldesc_t* front_desc; + // Remove a descriptor from the DMA complete event queue + xQueueReceiveFromISR(o_dma.queue, &front_desc, &high_priority_task_awoken); + I2S_OUT_PULSER_ENTER_CRITICAL_ISR(); + uint32_t port_data = 0; + if (i2s_out_pulser_status == STEPPING) { + port_data = atomic_load(&i2s_out_port_data); + } + I2S_OUT_PULSER_EXIT_CRITICAL_ISR(); + for (int i = 0; i < DMA_SAMPLE_COUNT; i++) { + front_desc->buf[i] = port_data; + } + front_desc->length = I2S_OUT_DMABUF_LEN; + } + + // Send a DMA complete event to the I2S bitstreamer task with finished buffer + xQueueSendFromISR(o_dma.queue, &finish_desc, &high_priority_task_awoken); } - // Send a DMA complete event to the I2S bitstreamer task with finished buffer - xQueueSendFromISR(o_dma.queue, &finish_desc, &high_priority_task_awoken); - } + if (high_priority_task_awoken == pdTRUE) + portYIELD_FROM_ISR(); - if (high_priority_task_awoken == pdTRUE) portYIELD_FROM_ISR(); - - // clear interrupt - I2S0.int_clr.val = I2S0.int_st.val; //clear pending interrupt + // clear interrupt + I2S0.int_clr.val = I2S0.int_st.val; //clear pending interrupt } // // I2S bitstream generator task // static void IRAM_ATTR i2sOutTask(void* parameter) { - lldesc_t *dma_desc; - while (1) { - // Wait a DMA complete event from I2S isr - // (Block until a DMA transfer has complete) - xQueueReceive(o_dma.queue, &dma_desc, portMAX_DELAY); - o_dma.current = (uint32_t*)(dma_desc->buf); - // It reuses the oldest (just transferred) buffer with the name "current" - // and fills the buffer for later DMA. - I2S_OUT_PULSER_ENTER_CRITICAL(); // Lock pulser status - if (i2s_out_pulser_status == STEPPING) { - // - // Fillout the buffer for pulse - // - // To avoid buffer overflow, all of the maximum pulse width (normaly about 10us) - // is adjusted to be in a single buffer. - // DMA_SAMPLE_SAFE_COUNT is referred to as the margin value. - // Therefore, if a buffer is close to full and it is time to generate a pulse, - // the generation of the buffer is interrupted (the buffer length is shortened slightly) - // and the pulse generation is postponed until the next buffer is filled. - // - i2s_fillout_dma_buffer(dma_desc); - dma_desc->length = o_dma.rw_pos * I2S_SAMPLE_SIZE; - } else if (i2s_out_pulser_status == WAITING) { - if (dma_desc->qe.stqe_next == NULL) { - // Tail of the DMA descriptor found - // I2S TX module has alrewdy stopped by ISR - i2s_out_stop(); - i2s_clear_o_dma_buffers(0); // 0 for static I2S control mode (right ch. data is always 0) - // You need to set the status before calling i2s_out_start() - // because the process in i2s_out_start() is different depending on the status. - i2s_out_pulser_status = PASSTHROUGH; - i2s_out_start(); - } else { - // Processing a buffer slightly ahead of the tail buffer. - // We don't need to fill up the buffer by port_data any more. - i2s_clear_dma_buffer(dma_desc, 0); // Essentially, no clearing is required. I'll make sure I know when I've written something. - o_dma.rw_pos = 0; // If someone calls i2s_out_push_sample, make sure there is no buffer overflow - dma_desc->qe.stqe_next = NULL; // Cut the DMA descriptor ring. This allow us to identify the tail of the buffer. - } - } else { - // Stepper paused (passthrough state, static I2S control mode) - // In the passthrough mode, there is no need to fill the buffer with port_data. - i2s_clear_dma_buffer(dma_desc, 0); // Essentially, no clearing is required. I'll make sure I know when I've written something. - o_dma.rw_pos = 0; // If someone calls i2s_out_push_sample, make sure there is no buffer overflow + lldesc_t* dma_desc; + while (1) { + // Wait a DMA complete event from I2S isr + // (Block until a DMA transfer has complete) + xQueueReceive(o_dma.queue, &dma_desc, portMAX_DELAY); + o_dma.current = (uint32_t*)(dma_desc->buf); + // It reuses the oldest (just transferred) buffer with the name "current" + // and fills the buffer for later DMA. + I2S_OUT_PULSER_ENTER_CRITICAL(); // Lock pulser status + if (i2s_out_pulser_status == STEPPING) { + // + // Fillout the buffer for pulse + // + // To avoid buffer overflow, all of the maximum pulse width (normaly about 10us) + // is adjusted to be in a single buffer. + // DMA_SAMPLE_SAFE_COUNT is referred to as the margin value. + // Therefore, if a buffer is close to full and it is time to generate a pulse, + // the generation of the buffer is interrupted (the buffer length is shortened slightly) + // and the pulse generation is postponed until the next buffer is filled. + // + i2s_fillout_dma_buffer(dma_desc); + dma_desc->length = o_dma.rw_pos * I2S_SAMPLE_SIZE; + } else if (i2s_out_pulser_status == WAITING) { + if (dma_desc->qe.stqe_next == NULL) { + // Tail of the DMA descriptor found + // I2S TX module has alrewdy stopped by ISR + i2s_out_stop(); + i2s_clear_o_dma_buffers(0); // 0 for static I2S control mode (right ch. data is always 0) + // You need to set the status before calling i2s_out_start() + // because the process in i2s_out_start() is different depending on the status. + i2s_out_pulser_status = PASSTHROUGH; + i2s_out_start(); + } else { + // Processing a buffer slightly ahead of the tail buffer. + // We don't need to fill up the buffer by port_data any more. + i2s_clear_dma_buffer(dma_desc, 0); // Essentially, no clearing is required. I'll make sure I know when I've written something. + o_dma.rw_pos = 0; // If someone calls i2s_out_push_sample, make sure there is no buffer overflow + dma_desc->qe.stqe_next = NULL; // Cut the DMA descriptor ring. This allow us to identify the tail of the buffer. + } + } else { + // Stepper paused (passthrough state, static I2S control mode) + // In the passthrough mode, there is no need to fill the buffer with port_data. + i2s_clear_dma_buffer(dma_desc, 0); // Essentially, no clearing is required. I'll make sure I know when I've written something. + o_dma.rw_pos = 0; // If someone calls i2s_out_push_sample, make sure there is no buffer overflow + } + I2S_OUT_PULSER_EXIT_CRITICAL(); // Unlock pulser status } - I2S_OUT_PULSER_EXIT_CRITICAL(); // Unlock pulser status - } } -#endif +# endif // // External funtions // void IRAM_ATTR i2s_out_delay() { -#ifdef USE_I2S_OUT_STREAM - I2S_OUT_PULSER_ENTER_CRITICAL(); - if (i2s_out_pulser_status == PASSTHROUGH) { - // Depending on the timing, it may not be reflected immediately, - // so wait twice as long just in case. +# ifdef USE_I2S_OUT_STREAM + I2S_OUT_PULSER_ENTER_CRITICAL(); + if (i2s_out_pulser_status == PASSTHROUGH) { + // Depending on the timing, it may not be reflected immediately, + // so wait twice as long just in case. + ets_delay_us(I2S_OUT_USEC_PER_PULSE * 2); + } else { + // Just wait until the data now registered in the DMA descripter + // is reflected in the I2S TX module via FIFO. + delay(I2S_OUT_DELAY_MS); + } + I2S_OUT_PULSER_EXIT_CRITICAL(); +# else ets_delay_us(I2S_OUT_USEC_PER_PULSE * 2); - } else { - // Just wait until the data now registered in the DMA descripter - // is reflected in the I2S TX module via FIFO. - delay(I2S_OUT_DELAY_MS); - } - I2S_OUT_PULSER_EXIT_CRITICAL(); -#else - ets_delay_us(I2S_OUT_USEC_PER_PULSE * 2); -#endif +# endif } void IRAM_ATTR i2s_out_write(uint8_t pin, uint8_t val) { - uint32_t bit = bit(pin); - if (val) { - atomic_fetch_or(&i2s_out_port_data, bit); - } else { - atomic_fetch_and(&i2s_out_port_data, ~bit); - } -#ifdef USE_I2S_OUT_STREAM - // It needs a lock for access, but I've given up because I need speed. - // This is not a problem as long as there is no overlap between the status change and digitalWrite(). - if (i2s_out_pulser_status == PASSTHROUGH) { + uint32_t bit = bit(pin); + if (val) { + atomic_fetch_or(&i2s_out_port_data, bit); + } else { + atomic_fetch_and(&i2s_out_port_data, ~bit); + } +# ifdef USE_I2S_OUT_STREAM + // It needs a lock for access, but I've given up because I need speed. + // This is not a problem as long as there is no overlap between the status change and digitalWrite(). + if (i2s_out_pulser_status == PASSTHROUGH) { + i2s_out_single_data(); + } +# else i2s_out_single_data(); - } -#else - i2s_out_single_data(); -#endif +# endif } uint8_t IRAM_ATTR i2s_out_state(uint8_t pin) { - uint32_t port_data = atomic_load(&i2s_out_port_data); - return (!!(port_data & bit(pin))); + uint32_t port_data = atomic_load(&i2s_out_port_data); + return (!!(port_data & bit(pin))); } uint32_t IRAM_ATTR i2s_out_push_sample(uint32_t num) { -#ifdef USE_I2S_OUT_STREAM - if (num > SAMPLE_SAFE_COUNT) { +# ifdef USE_I2S_OUT_STREAM + if (num > SAMPLE_SAFE_COUNT) { + return 0; + } + // push at least one sample (even if num is zero) + uint32_t port_data = atomic_load(&i2s_out_port_data); + uint32_t n = 0; + do { + o_dma.current[o_dma.rw_pos++] = port_data; + n++; + } while (n < num); + return n; +# else return 0; - } - // push at least one sample (even if num is zero) - uint32_t port_data = atomic_load(&i2s_out_port_data); - uint32_t n = 0; - do { - o_dma.current[o_dma.rw_pos++] = port_data; - n++; - } while(n < num); - return n; -#else - return 0; -#endif +# endif } int IRAM_ATTR i2s_out_set_passthrough() { - I2S_OUT_PULSER_ENTER_CRITICAL(); -#ifdef USE_I2S_OUT_STREAM - if (i2s_out_pulser_status == STEPPING) { - i2s_out_pulser_status = WAITING; // Start stopping the pulser - } -#else - i2s_out_pulser_status = PASSTHROUGH; -#endif - I2S_OUT_PULSER_EXIT_CRITICAL(); - return 0; + I2S_OUT_PULSER_ENTER_CRITICAL(); +# ifdef USE_I2S_OUT_STREAM + if (i2s_out_pulser_status == STEPPING) { + i2s_out_pulser_status = WAITING; // Start stopping the pulser + } +# else + i2s_out_pulser_status = PASSTHROUGH; +# endif + I2S_OUT_PULSER_EXIT_CRITICAL(); + return 0; } int IRAM_ATTR i2s_out_set_stepping() { - I2S_OUT_PULSER_ENTER_CRITICAL(); -#ifdef USE_I2S_OUT_STREAM - if (i2s_out_pulser_status == STEPPING) { - // Re-entered (fail safe) + I2S_OUT_PULSER_ENTER_CRITICAL(); +# ifdef USE_I2S_OUT_STREAM + if (i2s_out_pulser_status == STEPPING) { + // Re-entered (fail safe) + I2S_OUT_PULSER_EXIT_CRITICAL(); + return 0; + } + + if (i2s_out_pulser_status == WAITING) { + // Wait for complete DMAs + for (;;) { + I2S_OUT_PULSER_EXIT_CRITICAL(); + delay(I2S_OUT_DELAY_DMABUF_MS); + I2S_OUT_PULSER_ENTER_CRITICAL(); + if (i2s_out_pulser_status == WAITING) { + continue; + } + if (i2s_out_pulser_status == PASSTHROUGH) { + // DMA completed + break; + } + // Another function change the I2S state to STEPPING + I2S_OUT_PULSER_EXIT_CRITICAL(); + return 0; + } + } + + // Change I2S state from PASSTHROUGH to STEPPING + i2s_out_stop(); + uint32_t port_data = atomic_load(&i2s_out_port_data); + i2s_clear_o_dma_buffers(port_data); + + // You need to set the status before calling i2s_out_start() + // because the process in i2s_out_start() is different depending on the status. + i2s_out_pulser_status = STEPPING; + i2s_out_start(); +# else + i2s_out_pulser_status = STEPPING; +# endif I2S_OUT_PULSER_EXIT_CRITICAL(); return 0; - } - - if (i2s_out_pulser_status == WAITING) { - // Wait for complete DMAs - for(;;) { - I2S_OUT_PULSER_EXIT_CRITICAL(); - delay(I2S_OUT_DELAY_DMABUF_MS); - I2S_OUT_PULSER_ENTER_CRITICAL(); - if (i2s_out_pulser_status == WAITING) { - continue; - } - if (i2s_out_pulser_status == PASSTHROUGH) { - // DMA completed - break; - } - // Another function change the I2S state to STEPPING - I2S_OUT_PULSER_EXIT_CRITICAL(); - return 0; - } - } - - // Change I2S state from PASSTHROUGH to STEPPING - i2s_out_stop(); - uint32_t port_data = atomic_load(&i2s_out_port_data); - i2s_clear_o_dma_buffers(port_data); - - // You need to set the status before calling i2s_out_start() - // because the process in i2s_out_start() is different depending on the status. - i2s_out_pulser_status = STEPPING; - i2s_out_start(); -#else - i2s_out_pulser_status = STEPPING; -#endif - I2S_OUT_PULSER_EXIT_CRITICAL(); - return 0; } int IRAM_ATTR i2s_out_set_pulse_period(uint32_t period) { -#ifdef USE_I2S_OUT_STREAM - i2s_out_pulse_period = period; -#endif - return 0; +# ifdef USE_I2S_OUT_STREAM + i2s_out_pulse_period = period; +# endif + return 0; } int IRAM_ATTR i2s_out_set_pulse_callback(i2s_out_pulse_func_t func) { -#ifdef USE_I2S_OUT_STREAM - i2s_out_pulse_func = func; -#endif - return 0; +# ifdef USE_I2S_OUT_STREAM + i2s_out_pulse_func = func; +# endif + return 0; } int IRAM_ATTR i2s_out_reset() { - I2S_OUT_PULSER_ENTER_CRITICAL(); - i2s_out_stop(); -#ifdef USE_I2S_OUT_STREAM - if (i2s_out_pulser_status == STEPPING) { - uint32_t port_data = atomic_load(&i2s_out_port_data); - i2s_clear_o_dma_buffers(port_data); - } else if (i2s_out_pulser_status == WAITING) { - i2s_clear_o_dma_buffers(0); - i2s_out_pulser_status = PASSTHROUGH; - } -#endif - // You need to set the status before calling i2s_out_start() - // because the process in i2s_out_start() is different depending on the status. - i2s_out_start(); - I2S_OUT_PULSER_EXIT_CRITICAL(); - return 0; + I2S_OUT_PULSER_ENTER_CRITICAL(); + i2s_out_stop(); +# ifdef USE_I2S_OUT_STREAM + if (i2s_out_pulser_status == STEPPING) { + uint32_t port_data = atomic_load(&i2s_out_port_data); + i2s_clear_o_dma_buffers(port_data); + } else if (i2s_out_pulser_status == WAITING) { + i2s_clear_o_dma_buffers(0); + i2s_out_pulser_status = PASSTHROUGH; + } +# endif + // You need to set the status before calling i2s_out_start() + // because the process in i2s_out_start() is different depending on the status. + i2s_out_start(); + I2S_OUT_PULSER_EXIT_CRITICAL(); + return 0; } // // Initialize funtion (external function) // -int IRAM_ATTR i2s_out_init(i2s_out_init_t &init_param) { - if (i2s_out_initialized) { - // already initialized - return -1; - } +int IRAM_ATTR i2s_out_init(i2s_out_init_t& init_param) { + if (i2s_out_initialized) { + // already initialized + return -1; + } - atomic_store(&i2s_out_port_data, init_param.init_val); + atomic_store(&i2s_out_port_data, init_param.init_val); - // To make sure hardware is enabled before any hardware register operations. - periph_module_reset(PERIPH_I2S0_MODULE); - periph_module_enable(PERIPH_I2S0_MODULE); + // To make sure hardware is enabled before any hardware register operations. + periph_module_reset(PERIPH_I2S0_MODULE); + periph_module_enable(PERIPH_I2S0_MODULE); - // Route the i2s pins to the appropriate GPIO - i2s_out_gpio_attach(init_param.ws_pin, init_param.bck_pin, init_param.data_pin); + // Route the i2s pins to the appropriate GPIO + i2s_out_gpio_attach(init_param.ws_pin, init_param.bck_pin, init_param.data_pin); - /** + /** * Each i2s transfer will take * fpll = PLL_D2_CLK -- clka_en = 0 * @@ -686,207 +686,211 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t &init_param) { * M = 2 */ -#ifdef USE_I2S_OUT_STREAM - // Allocate the array of pointers to the buffers - o_dma.buffers = (uint32_t **)malloc(sizeof(uint32_t*) * I2S_OUT_DMABUF_COUNT); - if (o_dma.buffers == nullptr) return -1; +# ifdef USE_I2S_OUT_STREAM + // Allocate the array of pointers to the buffers + o_dma.buffers = (uint32_t**)malloc(sizeof(uint32_t*) * I2S_OUT_DMABUF_COUNT); + if (o_dma.buffers == nullptr) + return -1; - // Allocate each buffer that can be used by the DMA controller - for (int buf_idx = 0; buf_idx < I2S_OUT_DMABUF_COUNT; buf_idx++) { - o_dma.buffers[buf_idx] = (uint32_t*) heap_caps_calloc(1, I2S_OUT_DMABUF_LEN, MALLOC_CAP_DMA); - if (o_dma.buffers[buf_idx] == nullptr) return -1; - } + // Allocate each buffer that can be used by the DMA controller + for (int buf_idx = 0; buf_idx < I2S_OUT_DMABUF_COUNT; buf_idx++) { + o_dma.buffers[buf_idx] = (uint32_t*)heap_caps_calloc(1, I2S_OUT_DMABUF_LEN, MALLOC_CAP_DMA); + if (o_dma.buffers[buf_idx] == nullptr) + return -1; + } - // Allocate the array of DMA descriptors - o_dma.desc = (lldesc_t**) malloc(sizeof(lldesc_t*) * I2S_OUT_DMABUF_COUNT); - if (o_dma.desc == nullptr) return -1; + // Allocate the array of DMA descriptors + o_dma.desc = (lldesc_t**)malloc(sizeof(lldesc_t*) * I2S_OUT_DMABUF_COUNT); + if (o_dma.desc == nullptr) + return -1; - // Allocate each DMA descriptor that will be used by the DMA controller - for (int buf_idx = 0; buf_idx < I2S_OUT_DMABUF_COUNT; buf_idx++) { - o_dma.desc[buf_idx] = (lldesc_t*) heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA); - if (o_dma.desc[buf_idx] == nullptr) return -1; - } + // Allocate each DMA descriptor that will be used by the DMA controller + for (int buf_idx = 0; buf_idx < I2S_OUT_DMABUF_COUNT; buf_idx++) { + o_dma.desc[buf_idx] = (lldesc_t*)heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA); + if (o_dma.desc[buf_idx] == nullptr) + return -1; + } - // Initialize - i2s_clear_o_dma_buffers(init_param.init_val); - o_dma.rw_pos = 0; - o_dma.current = NULL; - o_dma.queue = xQueueCreate(I2S_OUT_DMABUF_COUNT, sizeof(uint32_t *)); + // Initialize + i2s_clear_o_dma_buffers(init_param.init_val); + o_dma.rw_pos = 0; + o_dma.current = NULL; + o_dma.queue = xQueueCreate(I2S_OUT_DMABUF_COUNT, sizeof(uint32_t*)); - // Set the first DMA descriptor - I2S0.out_link.addr = (uint32_t)o_dma.desc[0]; -#endif + // Set the first DMA descriptor + I2S0.out_link.addr = (uint32_t)o_dma.desc[0]; +# endif - // stop i2s - I2S0.out_link.stop = 1; - I2S0.conf.tx_start = 0; + // stop i2s + I2S0.out_link.stop = 1; + I2S0.conf.tx_start = 0; - I2S0.int_clr.val = I2S0.int_st.val; //clear pending interrupt + I2S0.int_clr.val = I2S0.int_st.val; //clear pending interrupt - // - // i2s_param_config - // + // + // i2s_param_config + // - // configure I2S data port interface. - i2s_out_reset_fifo(); + // configure I2S data port interface. + i2s_out_reset_fifo(); - //reset i2s - I2S0.conf.tx_reset = 1; - I2S0.conf.tx_reset = 0; - I2S0.conf.rx_reset = 1; - I2S0.conf.rx_reset = 0; + //reset i2s + I2S0.conf.tx_reset = 1; + I2S0.conf.tx_reset = 0; + I2S0.conf.rx_reset = 1; + I2S0.conf.rx_reset = 0; - //reset dma - I2S0.lc_conf.in_rst = 1; // Set this bit to reset in DMA FSM. (R/W) - I2S0.lc_conf.in_rst = 0; - I2S0.lc_conf.out_rst = 1; // Set this bit to reset out DMA FSM. (R/W) - I2S0.lc_conf.out_rst = 0; + //reset dma + I2S0.lc_conf.in_rst = 1; // Set this bit to reset in DMA FSM. (R/W) + I2S0.lc_conf.in_rst = 0; + I2S0.lc_conf.out_rst = 1; // Set this bit to reset out DMA FSM. (R/W) + I2S0.lc_conf.out_rst = 0; - //Enable and configure DMA - I2S0.lc_conf.check_owner = 0; - I2S0.lc_conf.out_loop_test = 0; - I2S0.lc_conf.out_auto_wrback = 0; // Disable auto outlink-writeback when all the data has been transmitted - I2S0.lc_conf.out_data_burst_en = 0; - I2S0.lc_conf.outdscr_burst_en = 0; - I2S0.lc_conf.out_no_restart_clr = 0; - I2S0.lc_conf.indscr_burst_en = 0; -#ifdef USE_I2S_OUT_STREAM - I2S0.lc_conf.out_eof_mode = 1; // I2S_OUT_EOF_INT generated when DMA has popped all data from the FIFO; -#endif - I2S0.conf2.lcd_en = 0; - I2S0.conf2.camera_en = 0; - I2S0.pdm_conf.pcm2pdm_conv_en = 0; - I2S0.pdm_conf.pdm2pcm_conv_en = 0; + //Enable and configure DMA + I2S0.lc_conf.check_owner = 0; + I2S0.lc_conf.out_loop_test = 0; + I2S0.lc_conf.out_auto_wrback = 0; // Disable auto outlink-writeback when all the data has been transmitted + I2S0.lc_conf.out_data_burst_en = 0; + I2S0.lc_conf.outdscr_burst_en = 0; + I2S0.lc_conf.out_no_restart_clr = 0; + I2S0.lc_conf.indscr_burst_en = 0; +# ifdef USE_I2S_OUT_STREAM + I2S0.lc_conf.out_eof_mode = 1; // I2S_OUT_EOF_INT generated when DMA has popped all data from the FIFO; +# endif + I2S0.conf2.lcd_en = 0; + I2S0.conf2.camera_en = 0; + I2S0.pdm_conf.pcm2pdm_conv_en = 0; + I2S0.pdm_conf.pdm2pcm_conv_en = 0; - I2S0.fifo_conf.dscr_en = 0; + I2S0.fifo_conf.dscr_en = 0; -#ifdef USE_I2S_OUT_STREAM - if (i2s_out_pulser_status == STEPPING) { - // Stream output mode - I2S0.conf_chan.tx_chan_mod = 4; // 3:right+constant 4:left+constant (when tx_msb_right = 1) - I2S0.conf_single_data = 0; - } else { - // Static output mode - I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1) - I2S0.conf_single_data = init_param.init_val; - } -#else - // For the static output mode - I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1) - I2S0.conf_single_data = init_param.init_val; // initial constant value -#endif -#if I2S_OUT_NUM_BITS == 16 - I2S0.fifo_conf.tx_fifo_mod = 0; // 0: 16-bit dual channel data, 3: 32-bit single channel data - I2S0.fifo_conf.rx_fifo_mod = 0; // 0: 16-bit dual channel data, 3: 32-bit single channel data - I2S0.sample_rate_conf.tx_bits_mod = 16; // default is 16-bits - I2S0.sample_rate_conf.rx_bits_mod = 16; // default is 16-bits -#else - I2S0.fifo_conf.tx_fifo_mod = 3; // 0: 16-bit dual channel data, 3: 32-bit single channel data - I2S0.fifo_conf.rx_fifo_mod = 3; // 0: 16-bit dual channel data, 3: 32-bit single channel data - // Data width is 32-bit. Forgetting this setting will result in a 16-bit transfer. - I2S0.sample_rate_conf.tx_bits_mod = 32; - I2S0.sample_rate_conf.rx_bits_mod = 32; -#endif - I2S0.conf.tx_mono = 0; // Set this bit to enable transmitter’s mono mode in PCM standard mode. +# ifdef USE_I2S_OUT_STREAM + if (i2s_out_pulser_status == STEPPING) { + // Stream output mode + I2S0.conf_chan.tx_chan_mod = 4; // 3:right+constant 4:left+constant (when tx_msb_right = 1) + I2S0.conf_single_data = 0; + } else { + // Static output mode + I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1) + I2S0.conf_single_data = init_param.init_val; + } +# else + // For the static output mode + I2S0.conf_chan.tx_chan_mod = 3; // 3:right+constant 4:left+constant (when tx_msb_right = 1) + I2S0.conf_single_data = init_param.init_val; // initial constant value +# endif +# if I2S_OUT_NUM_BITS == 16 + I2S0.fifo_conf.tx_fifo_mod = 0; // 0: 16-bit dual channel data, 3: 32-bit single channel data + I2S0.fifo_conf.rx_fifo_mod = 0; // 0: 16-bit dual channel data, 3: 32-bit single channel data + I2S0.sample_rate_conf.tx_bits_mod = 16; // default is 16-bits + I2S0.sample_rate_conf.rx_bits_mod = 16; // default is 16-bits +# else + I2S0.fifo_conf.tx_fifo_mod = 3; // 0: 16-bit dual channel data, 3: 32-bit single channel data + I2S0.fifo_conf.rx_fifo_mod = 3; // 0: 16-bit dual channel data, 3: 32-bit single channel data + // Data width is 32-bit. Forgetting this setting will result in a 16-bit transfer. + I2S0.sample_rate_conf.tx_bits_mod = 32; + I2S0.sample_rate_conf.rx_bits_mod = 32; +# endif + I2S0.conf.tx_mono = 0; // Set this bit to enable transmitter’s mono mode in PCM standard mode. - I2S0.conf_chan.rx_chan_mod = 1; // 1: right+right - I2S0.conf.rx_mono = 0; + I2S0.conf_chan.rx_chan_mod = 1; // 1: right+right + I2S0.conf.rx_mono = 0; -#ifdef USE_I2S_OUT_STREAM - I2S0.fifo_conf.dscr_en = 1; //connect DMA to fifo -#endif - I2S0.conf.tx_start = 0; - I2S0.conf.rx_start = 0; +# ifdef USE_I2S_OUT_STREAM + I2S0.fifo_conf.dscr_en = 1; //connect DMA to fifo +# endif + I2S0.conf.tx_start = 0; + I2S0.conf.rx_start = 0; - I2S0.conf.tx_msb_right = 1; // Set this bit to place right-channel data at the MSB in the transmit FIFO. - I2S0.conf.tx_right_first = 0; // Setting this bit allows the right-channel data to be sent first. + I2S0.conf.tx_msb_right = 1; // Set this bit to place right-channel data at the MSB in the transmit FIFO. + I2S0.conf.tx_right_first = 0; // Setting this bit allows the right-channel data to be sent first. - I2S0.conf.tx_slave_mod = 0; // Master -#ifdef USE_I2S_OUT_STREAM - I2S0.fifo_conf.tx_fifo_mod_force_en = 1; //The bit should always be set to 1. -#endif - I2S0.pdm_conf.rx_pdm_en = 0; // Set this bit to enable receiver’s PDM mode. - I2S0.pdm_conf.tx_pdm_en = 0; // Set this bit to enable transmitter’s PDM mode. + I2S0.conf.tx_slave_mod = 0; // Master +# ifdef USE_I2S_OUT_STREAM + I2S0.fifo_conf.tx_fifo_mod_force_en = 1; //The bit should always be set to 1. +# endif + I2S0.pdm_conf.rx_pdm_en = 0; // Set this bit to enable receiver’s PDM mode. + I2S0.pdm_conf.tx_pdm_en = 0; // Set this bit to enable transmitter’s PDM mode. - // I2S_COMM_FORMAT_I2S_LSB - I2S0.conf.tx_short_sync = 0; // Set this bit to enable transmitter in PCM standard mode. - I2S0.conf.rx_short_sync = 0; // Set this bit to enable receiver in PCM standard mode. - I2S0.conf.tx_msb_shift = 0; // Do not use the Philips standard to avoid bit-shifting - I2S0.conf.rx_msb_shift = 0; // Do not use the Philips standard to avoid bit-shifting + // I2S_COMM_FORMAT_I2S_LSB + I2S0.conf.tx_short_sync = 0; // Set this bit to enable transmitter in PCM standard mode. + I2S0.conf.rx_short_sync = 0; // Set this bit to enable receiver in PCM standard mode. + I2S0.conf.tx_msb_shift = 0; // Do not use the Philips standard to avoid bit-shifting + I2S0.conf.rx_msb_shift = 0; // Do not use the Philips standard to avoid bit-shifting - // - // i2s_set_clk - // + // + // i2s_set_clk + // - // set clock (fi2s) 160MHz / 5 - I2S0.clkm_conf.clka_en = 0; // Use 160 MHz PLL_D2_CLK as reference - // N + b/a = 0 -#if I2S_OUT_NUM_BITS == 16 - // N = 10 - I2S0.clkm_conf.clkm_div_num = 10; // minimum value of 2, reset value of 4, max 256 (I²S clock divider’s integral value) -#else - // N = 5 - I2S0.clkm_conf.clkm_div_num = 5; // minimum value of 2, reset value of 4, max 256 (I²S clock divider’s integral value) -#endif - // b/a = 0 - I2S0.clkm_conf.clkm_div_b = 0; // 0 at reset - I2S0.clkm_conf.clkm_div_a = 0; // 0 at reset, what about divide by 0? (not an issue) + // set clock (fi2s) 160MHz / 5 + I2S0.clkm_conf.clka_en = 0; // Use 160 MHz PLL_D2_CLK as reference + // N + b/a = 0 +# if I2S_OUT_NUM_BITS == 16 + // N = 10 + I2S0.clkm_conf.clkm_div_num = 10; // minimum value of 2, reset value of 4, max 256 (I²S clock divider’s integral value) +# else + // N = 5 + I2S0.clkm_conf.clkm_div_num = 5; // minimum value of 2, reset value of 4, max 256 (I²S clock divider’s integral value) +# endif + // b/a = 0 + I2S0.clkm_conf.clkm_div_b = 0; // 0 at reset + I2S0.clkm_conf.clkm_div_a = 0; // 0 at reset, what about divide by 0? (not an issue) - // Bit clock configuration bit in transmitter mode. - // fbck = fi2s / tx_bck_div_num = (160 MHz / 5) / 2 = 16 MHz - I2S0.sample_rate_conf.tx_bck_div_num = 2; // minimum value of 2 defaults to 6 - I2S0.sample_rate_conf.rx_bck_div_num = 2; + // Bit clock configuration bit in transmitter mode. + // fbck = fi2s / tx_bck_div_num = (160 MHz / 5) / 2 = 16 MHz + I2S0.sample_rate_conf.tx_bck_div_num = 2; // minimum value of 2 defaults to 6 + I2S0.sample_rate_conf.rx_bck_div_num = 2; -#ifdef USE_I2S_OUT_STREAM - // Enable TX interrupts (DMA Interrupts) - I2S0.int_ena.out_eof = 1; // Triggered when rxlink has finished sending a packet. - I2S0.int_ena.out_dscr_err = 0; // Triggered when invalid rxlink descriptors are encountered. - I2S0.int_ena.out_total_eof = 1; // Triggered when all transmitting linked lists are used up. - I2S0.int_ena.out_done = 0; // Triggered when all transmitted and buffered data have been read. +# ifdef USE_I2S_OUT_STREAM + // Enable TX interrupts (DMA Interrupts) + I2S0.int_ena.out_eof = 1; // Triggered when rxlink has finished sending a packet. + I2S0.int_ena.out_dscr_err = 0; // Triggered when invalid rxlink descriptors are encountered. + I2S0.int_ena.out_total_eof = 1; // Triggered when all transmitting linked lists are used up. + I2S0.int_ena.out_done = 0; // Triggered when all transmitted and buffered data have been read. - // default pulse callback period (μsec) - i2s_out_pulse_period = init_param.pulse_period; - i2s_out_pulse_func = init_param.pulse_func; + // default pulse callback period (μsec) + i2s_out_pulse_period = init_param.pulse_period; + i2s_out_pulse_func = init_param.pulse_func; - // Create the task that will feed the buffer - xTaskCreatePinnedToCore(i2sOutTask, - "I2SOutTask", - 1024 * 10, - NULL, - 1, - nullptr, - CONFIG_ARDUINO_RUNNING_CORE // must run the task on same core - ); + // Create the task that will feed the buffer + xTaskCreatePinnedToCore(i2sOutTask, + "I2SOutTask", + 1024 * 10, + NULL, + 1, + nullptr, + CONFIG_ARDUINO_RUNNING_CORE // must run the task on same core + ); - // Allocate and Enable the I2S interrupt - esp_intr_alloc(ETS_I2S0_INTR_SOURCE, 0, i2s_out_intr_handler, nullptr, &i2s_out_isr_handle); - esp_intr_enable(i2s_out_isr_handle); -#endif + // Allocate and Enable the I2S interrupt + esp_intr_alloc(ETS_I2S0_INTR_SOURCE, 0, i2s_out_intr_handler, nullptr, &i2s_out_isr_handle); + esp_intr_enable(i2s_out_isr_handle); +# endif - // Remember GPIO pin numbers - i2s_out_ws_pin = init_param.ws_pin; - i2s_out_bck_pin = init_param.bck_pin; - i2s_out_data_pin = init_param.data_pin; - i2s_out_initialized = 1; + // Remember GPIO pin numbers + i2s_out_ws_pin = init_param.ws_pin; + i2s_out_bck_pin = init_param.bck_pin; + i2s_out_data_pin = init_param.data_pin; + i2s_out_initialized = 1; - // Start the I2S peripheral - i2s_out_start(); + // Start the I2S peripheral + i2s_out_start(); - return 0; + return 0; } -#ifndef I2S_OUT_WS -#define I2S_OUT_WS GPIO_NUM_17 -#endif -#ifndef I2S_OUT_BCK -#define I2S_OUT_BCK GPIO_NUM_22 -#endif -#ifndef I2S_OUT_DATA -#define I2S_OUT_DATA GPIO_NUM_21 -#endif -#ifndef I2S_OUT_INIT_VAL -#define I2S_OUT_INIT_VAL 0 -#endif +# ifndef I2S_OUT_WS +# define I2S_OUT_WS GPIO_NUM_17 +# endif +# ifndef I2S_OUT_BCK +# define I2S_OUT_BCK GPIO_NUM_22 +# endif +# ifndef I2S_OUT_DATA +# define I2S_OUT_DATA GPIO_NUM_21 +# endif +# ifndef I2S_OUT_INIT_VAL +# define I2S_OUT_INIT_VAL 0 +# endif /* Initialize I2S out by default parameters. @@ -894,12 +898,12 @@ int IRAM_ATTR i2s_out_init(i2s_out_init_t &init_param) { */ int IRAM_ATTR i2s_out_init() { i2s_out_init_t default_param = { - .ws_pin = I2S_OUT_WS, - .bck_pin = I2S_OUT_BCK, - .data_pin = I2S_OUT_DATA, - .pulse_func = NULL, + .ws_pin = I2S_OUT_WS, + .bck_pin = I2S_OUT_BCK, + .data_pin = I2S_OUT_DATA, + .pulse_func = NULL, .pulse_period = I2S_OUT_USEC_PER_PULSE, - .init_val = I2S_OUT_INIT_VAL, + .init_val = I2S_OUT_INIT_VAL, }; return i2s_out_init(default_param); } diff --git a/Grbl_Esp32/i2s_out.h b/Grbl_Esp32/i2s_out.h index b0255f3b..5c1078ca 100644 --- a/Grbl_Esp32/i2s_out.h +++ b/Grbl_Esp32/i2s_out.h @@ -45,34 +45,34 @@ // but the prerequisite USE_I2S_OUT is not defined, // it is forced to be defined. #ifdef USE_I2S_OUT_STREAM - #ifndef USE_I2S_OUT - #define USE_I2S_OUT - #endif +# ifndef USE_I2S_OUT +# define USE_I2S_OUT +# endif #endif #ifdef USE_I2S_OUT -#include +# include /* Assert */ -#if defined(I2S_OUT_NUM_BITS) - #if (I2S_OUT_NUM_BITS != 16) && (I2S_OUT_NUM_BITS != 32) - #error "I2S_OUT_NUM_BITS should be 16 or 32" - #endif -#else - #define I2S_OUT_NUM_BITS 32 -#endif +# if defined(I2S_OUT_NUM_BITS) +# if (I2S_OUT_NUM_BITS != 16) && (I2S_OUT_NUM_BITS != 32) +# error "I2S_OUT_NUM_BITS should be 16 or 32" +# endif +# else +# define I2S_OUT_NUM_BITS 32 +# endif -#define I2SO(n) (I2S_OUT_PIN_BASE + n) +# define I2SO(n) (I2S_OUT_PIN_BASE + n) /* 16-bit mode: 1000000 usec / ((160000000 Hz) / 10 / 2) x 16 bit/pulse x 2(stereo) = 4 usec/pulse */ /* 32-bit mode: 1000000 usec / ((160000000 Hz) / 5 / 2) x 32 bit/pulse x 2(stereo) = 4 usec/pulse */ -#define I2S_OUT_USEC_PER_PULSE 4 +# define I2S_OUT_USEC_PER_PULSE 4 -#define I2S_OUT_DMABUF_COUNT 5 /* number of DMA buffers to store data */ -#define I2S_OUT_DMABUF_LEN 2000 /* maximum size in bytes (4092 is DMA's limit) */ +# define I2S_OUT_DMABUF_COUNT 5 /* number of DMA buffers to store data */ +# define I2S_OUT_DMABUF_LEN 2000 /* maximum size in bytes (4092 is DMA's limit) */ -#define I2S_OUT_DELAY_DMABUF_MS (I2S_OUT_DMABUF_LEN / sizeof(uint32_t) * I2S_OUT_USEC_PER_PULSE / 1000) -#define I2S_OUT_DELAY_MS (I2S_OUT_DELAY_DMABUF_MS * (I2S_OUT_DMABUF_COUNT + 1)) +# define I2S_OUT_DELAY_DMABUF_MS (I2S_OUT_DMABUF_LEN / sizeof(uint32_t) * I2S_OUT_USEC_PER_PULSE / 1000) +# define I2S_OUT_DELAY_MS (I2S_OUT_DELAY_DMABUF_MS * (I2S_OUT_DMABUF_COUNT + 1)) typedef void (*i2s_out_pulse_func_t)(void); @@ -90,19 +90,19 @@ typedef struct { If I2S_OUT_PIN_BASE is set to 128, bit0:Expanded GPIO 128, 1: Expanded GPIO 129, ..., v: Expanded GPIO 159 */ - uint8_t ws_pin; - uint8_t bck_pin; - uint8_t data_pin; + uint8_t ws_pin; + uint8_t bck_pin; + uint8_t data_pin; i2s_out_pulse_func_t pulse_func; - uint32_t pulse_period; // aka step rate. - uint32_t init_val; + uint32_t pulse_period; // aka step rate. + uint32_t init_val; } i2s_out_init_t; /* Initialize I2S out by parameters. return -1 ... already initialized */ -int i2s_out_init(i2s_out_init_t &init_param); +int i2s_out_init(i2s_out_init_t& init_param); /* Initialize I2S out by default parameters. diff --git a/Grbl_Esp32/inputbuffer.cpp b/Grbl_Esp32/inputbuffer.cpp index 35f68bc0..0fb49325 100644 --- a/Grbl_Esp32/inputbuffer.cpp +++ b/Grbl_Esp32/inputbuffer.cpp @@ -18,31 +18,27 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifdef ARDUINO_ARCH_ESP32 - #include "config.h" #include "inputbuffer.h" InputBuffer inputBuffer; - InputBuffer::InputBuffer() { _RXbufferSize = 0; - _RXbufferpos = 0; + _RXbufferpos = 0; } InputBuffer::~InputBuffer() { _RXbufferSize = 0; - _RXbufferpos = 0; + _RXbufferpos = 0; } void InputBuffer::begin() { _RXbufferSize = 0; - _RXbufferpos = 0; + _RXbufferpos = 0; } void InputBuffer::end() { _RXbufferSize = 0; - _RXbufferpos = 0; + _RXbufferpos = 0; } InputBuffer::operator bool() const { @@ -65,7 +61,7 @@ size_t InputBuffer::write(uint8_t c) { if (current > (RXBUFFERSIZE - 1)) current = 0; _RXbuffer[current] = c; - current ++; + current++; _RXbufferSize += 1; return 1; } @@ -79,19 +75,23 @@ size_t InputBuffer::write(const uint8_t* buffer, size_t size) { } int InputBuffer::peek(void) { - if (_RXbufferSize > 0)return _RXbuffer[_RXbufferpos]; - else return -1; + if (_RXbufferSize > 0) + return _RXbuffer[_RXbufferpos]; + else + return -1; } bool InputBuffer::push(const char* data) { int data_size = strlen(data); if ((data_size + _RXbufferSize) <= RXBUFFERSIZE) { int current = _RXbufferpos + _RXbufferSize; - if (current > RXBUFFERSIZE) current = current - RXBUFFERSIZE; + if (current > RXBUFFERSIZE) + current = current - RXBUFFERSIZE; for (int i = 0; i < data_size; i++) { - if (current > (RXBUFFERSIZE - 1)) current = 0; + if (current > (RXBUFFERSIZE - 1)) + current = 0; _RXbuffer[current] = data[i]; - current ++; + current++; } _RXbufferSize += strlen(data); return true; @@ -103,16 +103,15 @@ int InputBuffer::read(void) { if (_RXbufferSize > 0) { int v = _RXbuffer[_RXbufferpos]; _RXbufferpos++; - if (_RXbufferpos > (RXBUFFERSIZE - 1))_RXbufferpos = 0; + if (_RXbufferpos > (RXBUFFERSIZE - 1)) + _RXbufferpos = 0; _RXbufferSize--; return v; - } else return -1; + } else + return -1; } void InputBuffer::flush(void) { //No need currently //keep for compatibility } - - -#endif // ARDUINO_ARCH_ESP32 diff --git a/Grbl_Esp32/inputbuffer.h b/Grbl_Esp32/inputbuffer.h index 9031f8ca..a0fbf2eb 100644 --- a/Grbl_Esp32/inputbuffer.h +++ b/Grbl_Esp32/inputbuffer.h @@ -20,45 +20,34 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "Print.h" +#include #define RXBUFFERSIZE 128 -class InputBuffer: public Print { - public: +class InputBuffer : public Print { +public: InputBuffer(); ~InputBuffer(); size_t write(uint8_t c); size_t write(const uint8_t* buffer, size_t size); - inline size_t write(const char* s) { - return write((uint8_t*) s, strlen(s)); - } - inline size_t write(unsigned long n) { - return write((uint8_t) n); - } - inline size_t write(long n) { - return write((uint8_t) n); - } - inline size_t write(unsigned int n) { - return write((uint8_t) n); - } - inline size_t write(int n) { - return write((uint8_t) n); - } - void begin(); - void end(); - int available(); - int availableforwrite(); - int peek(void); - int read(void); - bool push(const char* data); - void flush(void); - operator bool() const; - private: - uint8_t _RXbuffer[RXBUFFERSIZE]; + inline size_t write(const char* s) { return write((uint8_t*)s, strlen(s)); } + inline size_t write(unsigned long n) { return write((uint8_t)n); } + inline size_t write(long n) { return write((uint8_t)n); } + inline size_t write(unsigned int n) { return write((uint8_t)n); } + inline size_t write(int n) { return write((uint8_t)n); } + void begin(); + void end(); + int available(); + int availableforwrite(); + int peek(void); + int read(void); + bool push(const char* data); + void flush(void); + operator bool() const; + +private: + uint8_t _RXbuffer[RXBUFFERSIZE]; uint16_t _RXbufferSize; uint16_t _RXbufferpos; }; - extern InputBuffer inputBuffer; diff --git a/Grbl_Esp32/jog.cpp b/Grbl_Esp32/jog.cpp index 902b48f8..986f5048 100644 --- a/Grbl_Esp32/jog.cpp +++ b/Grbl_Esp32/jog.cpp @@ -23,7 +23,6 @@ #include "grbl.h" - // Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog. uint8_t jog_execute(plan_line_data_t* pl_data, parser_block_t* gc_block) { // Initialize planner data struct for jogging motions. @@ -34,12 +33,13 @@ uint8_t jog_execute(plan_line_data_t* pl_data, parser_block_t* gc_block) { pl_data->line_number = gc_block->values.n; #endif if (soft_limits->get()) { - if (system_check_travel_limits(gc_block->values.xyz)) return (STATUS_TRAVEL_EXCEEDED); + if (system_check_travel_limits(gc_block->values.xyz)) + return (STATUS_TRAVEL_EXCEEDED); } // Valid jog command. Plan, set state, and execute. mc_line(gc_block->values.xyz, pl_data); if (sys.state == STATE_IDLE) { - if (plan_get_current_block() != NULL) { // Check if there is a block to execute. + if (plan_get_current_block() != NULL) { // Check if there is a block to execute. sys.state = STATE_JOG; st_prep_buffer(); st_wake_up(); // NOTE: Manual start. No state machine required. diff --git a/Grbl_Esp32/jog.h b/Grbl_Esp32/jog.h index 4a4034ac..c3e997f2 100644 --- a/Grbl_Esp32/jog.h +++ b/Grbl_Esp32/jog.h @@ -24,9 +24,8 @@ #include "grbl.h" - // System motion line numbers must be zero. #define JOG_LINE_NUMBER 0 // Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog. -uint8_t jog_execute(plan_line_data_t *pl_data, parser_block_t *gc_block); +uint8_t jog_execute(plan_line_data_t* pl_data, parser_block_t* gc_block); diff --git a/Grbl_Esp32/machine.h b/Grbl_Esp32/machine.h index 3b6a64b9..9a907e06 100644 --- a/Grbl_Esp32/machine.h +++ b/Grbl_Esp32/machine.h @@ -1,5 +1,4 @@ #pragma once -// clang-format off // This file is where you choose the machine type, by including // one or more machine definition files as described below. @@ -17,7 +16,7 @@ PWM // !!! For initial testing, start with test_drive.h which disables // all I/O pins // #include "Machines/atari_1020.h" -#include "Machines/test_drive.h" +# include "Machines/test_drive.h" // !!! For actual use, change the line above to select a board // from Machines/, for example: @@ -48,8 +47,8 @@ PWM // supplied automatically. // MACHINE_PATHNAME_QUOTED constructs a path that is suitable for #include -#define MACHINE_PATHNAME_QUOTED(name) +# define MACHINE_PATHNAME_QUOTED(name) -#include MACHINE_PATHNAME_QUOTED(MACHINE_FILENAME) +# include MACHINE_PATHNAME_QUOTED(MACHINE_FILENAME) -#endif // MACHINE_FILENAME +#endif // MACHINE_FILENAME diff --git a/Grbl_Esp32/machine_common.h b/Grbl_Esp32/machine_common.h index 5706e30b..0cbc73c1 100644 --- a/Grbl_Esp32/machine_common.h +++ b/Grbl_Esp32/machine_common.h @@ -1,28 +1,28 @@ #pragma once #ifndef SPINDLE_TYPE - #define SPINDLE_TYPE SPINDLE_TYPE_PWM +# define SPINDLE_TYPE SPINDLE_TYPE_PWM #endif // Grbl setting that are common to all machines // It should not be necessary to change anything herein #ifndef GRBL_SPI_FREQ - // You can override these by defining them in a board file. - // To override, you must set all of them - //-1 means use the default board pin - #define GRBL_SPI_SS -1 - #define GRBL_SPI_MOSI -1 - #define GRBL_SPI_MISO -1 - #define GRBL_SPI_SCK -1 - #define GRBL_SPI_FREQ 4000000 +// You can override these by defining them in a board file. +// To override, you must set all of them +//-1 means use the default board pin +# define GRBL_SPI_SS -1 +# define GRBL_SPI_MOSI -1 +# define GRBL_SPI_MISO -1 +# define GRBL_SPI_SCK -1 +# define GRBL_SPI_FREQ 4000000 #endif // ESP32 CPU Settings -#define F_TIMERS 80000000 // a reference to the speed of ESP32 timers -#define F_STEPPER_TIMER 20000000 // frequency of step pulse timer -#define STEPPER_OFF_TIMER_PRESCALE 8 // gives a frequency of 10MHz -#define STEPPER_OFF_PERIOD_uSEC 3 // each tick is +#define F_TIMERS 80000000 // a reference to the speed of ESP32 timers +#define F_STEPPER_TIMER 20000000 // frequency of step pulse timer +#define STEPPER_OFF_TIMER_PRESCALE 8 // gives a frequency of 10MHz +#define STEPPER_OFF_PERIOD_uSEC 3 // each tick is #define STEP_PULSE_MIN 2 // uSeconds #define STEP_PULSE_MAX 10 // uSeconds diff --git a/Grbl_Esp32/motion_control.cpp b/Grbl_Esp32/motion_control.cpp index 190e3710..e0d822e0 100644 --- a/Grbl_Esp32/motion_control.cpp +++ b/Grbl_Esp32/motion_control.cpp @@ -28,17 +28,16 @@ // support it anyway. The following suppresses Intellisense // problem reports. #ifndef M_PI - #define M_PI 3.14159265358979323846 +# define M_PI 3.14159265358979323846 #endif uint8_t ganged_mode = SQUARING_MODE_DUAL; - // this allows kinematics to be used. void mc_line_kins(float* target, plan_line_data_t* pl_data, float* position) { #ifndef USE_KINEMATICS mc_line(target, pl_data); -#else // else use kinematics +#else // else use kinematics inverse_kinematics(target, pl_data, position); #endif } @@ -55,10 +54,12 @@ void mc_line(float* target, plan_line_data_t* pl_data) { // from everywhere in Grbl. if (soft_limits->get()) { // NOTE: Block jog state. Jogging is a special case and soft limits are handled independently. - if (sys.state != STATE_JOG) limits_soft_check(target); + if (sys.state != STATE_JOG) + limits_soft_check(target); } // If in check gcode mode, prevent motion by blocking planner. Soft limits still work. - if (sys.state == STATE_CHECK_MODE) return; + if (sys.state == STATE_CHECK_MODE) + return; // NOTE: Backlash compensation may be installed here. It will need direction info to track when // to insert a backlash line motion(s) before the intended line motion and will require its own // plan_check_full_buffer() and check for system abort loop. Also for position reporting @@ -75,17 +76,19 @@ void mc_line(float* target, plan_line_data_t* pl_data) { // If the buffer is full: good! That means we are well ahead of the robot. // Remain in this loop until there is room in the buffer. do { - protocol_execute_realtime(); // Check for any run-time commands - if (sys.abort) return; // Bail, if system abort. - if (plan_check_full_buffer()) protocol_auto_cycle_start(); // Auto-cycle start when buffer is full. - else break; + protocol_execute_realtime(); // Check for any run-time commands + if (sys.abort) + return; // Bail, if system abort. + if (plan_check_full_buffer()) + protocol_auto_cycle_start(); // Auto-cycle start when buffer is full. + else + break; } while (1); // Plan and queue motion into planner buffer // uint8_t plan_status; // Not used in normal operation. plan_buffer_line(target, pl_data); } - // Execute an arc in offset mode format. position == current xyz, target == target xyz, // offset == offset from current xyz, axis_X defines circle plane in tool space, axis_linear is // the direction of helical travel, radius == circle radius, isclockwise boolean. Used @@ -93,42 +96,50 @@ void mc_line(float* target, plan_line_data_t* pl_data) { // The arc is approximated by generating a huge number of tiny, linear segments. The chordal tolerance // of each segment is configured in the arc_tolerance setting, which is defined to be the maximum normal // distance from segment to the circle when the end points both lie on the circle. -void mc_arc(float* target, plan_line_data_t* pl_data, float* position, float* offset, float radius, - uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc) { +void mc_arc(float* target, + plan_line_data_t* pl_data, + float* position, + float* offset, + float radius, + uint8_t axis_0, + uint8_t axis_1, + uint8_t axis_linear, + uint8_t is_clockwise_arc) { float center_axis0 = position[axis_0] + offset[axis_0]; float center_axis1 = position[axis_1] + offset[axis_1]; - float r_axis0 = -offset[axis_0]; // Radius vector from center to current location - float r_axis1 = -offset[axis_1]; - float rt_axis0 = target[axis_0] - center_axis0; - float rt_axis1 = target[axis_1] - center_axis1; + float r_axis0 = -offset[axis_0]; // Radius vector from center to current location + float r_axis1 = -offset[axis_1]; + float rt_axis0 = target[axis_0] - center_axis0; + float rt_axis1 = target[axis_1] - center_axis1; #ifdef USE_KINEMATICS - float previous_position[N_AXIS]; + float previous_position[N_AXIS]; uint16_t n; for (n = 0; n < N_AXIS; n++) previous_position[n] = position[n]; #endif // CCW angle between position and target from circle center. Only one atan2() trig computation required. float angular_travel = atan2(r_axis0 * rt_axis1 - r_axis1 * rt_axis0, r_axis0 * rt_axis0 + r_axis1 * rt_axis1); - if (is_clockwise_arc) { // Correct atan2 output per direction - if (angular_travel >= -ARC_ANGULAR_TRAVEL_EPSILON) angular_travel -= 2 * M_PI; + if (is_clockwise_arc) { // Correct atan2 output per direction + if (angular_travel >= -ARC_ANGULAR_TRAVEL_EPSILON) + angular_travel -= 2 * M_PI; } else { - if (angular_travel <= ARC_ANGULAR_TRAVEL_EPSILON) angular_travel += 2 * M_PI; + if (angular_travel <= ARC_ANGULAR_TRAVEL_EPSILON) + angular_travel += 2 * M_PI; } // NOTE: Segment end points are on the arc, which can lead to the arc diameter being smaller by up to // (2x) arc_tolerance. For 99% of users, this is just fine. If a different arc segment fit // is desired, i.e. least-squares, midpoint on arc, just change the mm_per_arc_segment calculation. // For the intended uses of Grbl, this value shouldn't exceed 2000 for the strictest of cases. - uint16_t segments = floor(fabs(0.5 * angular_travel * radius) / - sqrt(arc_tolerance->get() * (2 * radius - arc_tolerance->get()))); + uint16_t segments = floor(fabs(0.5 * angular_travel * radius) / sqrt(arc_tolerance->get() * (2 * radius - arc_tolerance->get()))); if (segments) { // Multiply inverse feed_rate to compensate for the fact that this movement is approximated // by a number of discrete segments. The inverse feed_rate should be correct for the sum of // all segments. if (pl_data->condition & PL_COND_FLAG_INVERSE_TIME) { pl_data->feed_rate *= segments; - bit_false(pl_data->condition, PL_COND_FLAG_INVERSE_TIME); // Force as feed absolute mode over arc segments. + bit_false(pl_data->condition, PL_COND_FLAG_INVERSE_TIME); // Force as feed absolute mode over arc segments. } - float theta_per_segment = angular_travel / segments; + float theta_per_segment = angular_travel / segments; float linear_per_segment = (target[axis_linear] - position[axis_linear]) / segments; /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector, and phi is the angle of rotation. Solution approach by Jens Geisler. @@ -159,12 +170,12 @@ void mc_arc(float* target, plan_line_data_t* pl_data, float* position, float* of float cos_T = 2.0 - theta_per_segment * theta_per_segment; float sin_T = theta_per_segment * 0.16666667 * (cos_T + 4.0); cos_T *= 0.5; - float sin_Ti; - float cos_Ti; - float r_axisi; + float sin_Ti; + float cos_Ti; + float r_axisi; uint16_t i; - uint8_t count = 0; - for (i = 1; i < segments; i++) { // Increment (segments-1). + uint8_t count = 0; + for (i = 1; i < segments; i++) { // Increment (segments-1). if (count < N_ARC_CORRECTION) { // Apply vector rotation matrix. ~40 usec r_axisi = r_axis0 * sin_T + r_axis1 * cos_T; @@ -174,11 +185,11 @@ void mc_arc(float* target, plan_line_data_t* pl_data, float* position, float* of } else { // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments. ~375 usec // Compute exact location by applying transformation matrix from initial radius vector(=-offset). - cos_Ti = cos(i * theta_per_segment); - sin_Ti = sin(i * theta_per_segment); + cos_Ti = cos(i * theta_per_segment); + sin_Ti = sin(i * theta_per_segment); r_axis0 = -offset[axis_0] * cos_Ti + offset[axis_1] * sin_Ti; r_axis1 = -offset[axis_0] * sin_Ti - offset[axis_1] * cos_Ti; - count = 0; + count = 0; } // Update arc_target location position[axis_0] = center_axis0 + r_axis0; @@ -186,14 +197,15 @@ void mc_arc(float* target, plan_line_data_t* pl_data, float* position, float* of position[axis_linear] += linear_per_segment; #ifdef USE_KINEMATICS mc_line_kins(position, pl_data, previous_position); - previous_position[axis_0] = position[axis_0]; - previous_position[axis_1] = position[axis_1]; + previous_position[axis_0] = position[axis_0]; + previous_position[axis_1] = position[axis_1]; previous_position[axis_linear] = position[axis_linear]; #else mc_line(position, pl_data); #endif // Bail mid-circle on system abort. Runtime command check already performed by mc_line. - if (sys.abort) return; + if (sys.abort) + return; } } // Ensure last segment arrives at target location. @@ -204,15 +216,14 @@ void mc_arc(float* target, plan_line_data_t* pl_data, float* position, float* of #endif } - // Execute dwell in seconds. void mc_dwell(float seconds) { - if (sys.state == STATE_CHECK_MODE) return; + if (sys.state == STATE_CHECK_MODE) + return; protocol_buffer_synchronize(); delay_sec(seconds, DELAY_MODE_DWELL); } - // Perform homing cycle to locate and set machine zero. Only '$H' executes this command. // NOTE: There should be no motions in the buffer and Grbl must be in an idle state before // executing the homing cycle. This prevents incorrect buffered plans after homing. @@ -221,23 +232,23 @@ void mc_homing_cycle(uint8_t cycle_mask) { if (user_defined_homing()) return; #endif - // This give kinematics a chance to do something before normal homing - // if it returns true, the homing is canceled. + // This give kinematics a chance to do something before normal homing + // if it returns true, the homing is canceled. #ifdef USE_KINEMATICS if (kinematics_pre_homing(cycle_mask)) return; #endif - // Check and abort homing cycle, if hard limits are already enabled. Helps prevent problems - // with machines with limits wired on both ends of travel to one limit pin. - // TODO: Move the pin-specific LIMIT_PIN call to limits.c as a function. + // Check and abort homing cycle, if hard limits are already enabled. Helps prevent problems + // with machines with limits wired on both ends of travel to one limit pin. + // TODO: Move the pin-specific LIMIT_PIN call to limits.c as a function. #ifdef LIMITS_TWO_SWITCHES_ON_AXES if (limits_get_state()) { - mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown. + mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown. system_set_exec_alarm(EXEC_ALARM_HARD_LIMIT); return; } #endif - limits_disable(); // Disable hard limits pin change register for cycle duration + limits_disable(); // Disable hard limits pin change register for cycle duration // ------------------------------------------------------------------------------------- // Perform homing routine. NOTE: Special motion case. Only system reset works. n_homing_locate_cycle = N_HOMING_LOCATE_CYCLE; @@ -247,65 +258,65 @@ void mc_homing_cycle(uint8_t cycle_mask) { else */ if (cycle_mask) { - if (! axis_is_squared(cycle_mask)) + if (!axis_is_squared(cycle_mask)) limits_go_home(cycle_mask); // Homing cycle 0 else { - ganged_mode = SQUARING_MODE_DUAL; - n_homing_locate_cycle = 0; // don't do a second touch cycle + ganged_mode = SQUARING_MODE_DUAL; + n_homing_locate_cycle = 0; // don't do a second touch cycle limits_go_home(cycle_mask); - ganged_mode = SQUARING_MODE_A; - n_homing_locate_cycle = N_HOMING_LOCATE_CYCLE; // restore to default value + ganged_mode = SQUARING_MODE_A; + n_homing_locate_cycle = N_HOMING_LOCATE_CYCLE; // restore to default value limits_go_home(cycle_mask); ganged_mode = SQUARING_MODE_B; limits_go_home(cycle_mask); - ganged_mode = SQUARING_MODE_DUAL; // always return to dual + ganged_mode = SQUARING_MODE_DUAL; // always return to dual } - } // Perform homing cycle based on mask. + } // Perform homing cycle based on mask. else #endif { // Search to engage all axes limit switches at faster homing seek rate. - if (! axis_is_squared(HOMING_CYCLE_0)) + if (!axis_is_squared(HOMING_CYCLE_0)) limits_go_home(HOMING_CYCLE_0); // Homing cycle 0 else { - ganged_mode = SQUARING_MODE_DUAL; - n_homing_locate_cycle = 0; // don't do a second touch cycle + ganged_mode = SQUARING_MODE_DUAL; + n_homing_locate_cycle = 0; // don't do a second touch cycle limits_go_home(HOMING_CYCLE_0); - ganged_mode = SQUARING_MODE_A; - n_homing_locate_cycle = N_HOMING_LOCATE_CYCLE; // restore to default value + ganged_mode = SQUARING_MODE_A; + n_homing_locate_cycle = N_HOMING_LOCATE_CYCLE; // restore to default value limits_go_home(HOMING_CYCLE_0); ganged_mode = SQUARING_MODE_B; limits_go_home(HOMING_CYCLE_0); - ganged_mode = SQUARING_MODE_DUAL; // always return to dual + ganged_mode = SQUARING_MODE_DUAL; // always return to dual } #ifdef HOMING_CYCLE_1 - if (! axis_is_squared(HOMING_CYCLE_1)) + if (!axis_is_squared(HOMING_CYCLE_1)) limits_go_home(HOMING_CYCLE_1); else { - ganged_mode = SQUARING_MODE_DUAL; - n_homing_locate_cycle = 0; // don't do a second touch cycle + ganged_mode = SQUARING_MODE_DUAL; + n_homing_locate_cycle = 0; // don't do a second touch cycle limits_go_home(HOMING_CYCLE_1); - ganged_mode = SQUARING_MODE_A; - n_homing_locate_cycle = N_HOMING_LOCATE_CYCLE; // restore to default value + ganged_mode = SQUARING_MODE_A; + n_homing_locate_cycle = N_HOMING_LOCATE_CYCLE; // restore to default value limits_go_home(HOMING_CYCLE_1); ganged_mode = SQUARING_MODE_B; limits_go_home(HOMING_CYCLE_1); - ganged_mode = SQUARING_MODE_DUAL; // always return to dual + ganged_mode = SQUARING_MODE_DUAL; // always return to dual } #endif #ifdef HOMING_CYCLE_2 - if (! axis_is_squared(HOMING_CYCLE_2)) + if (!axis_is_squared(HOMING_CYCLE_2)) limits_go_home(HOMING_CYCLE_2); else { - ganged_mode = SQUARING_MODE_DUAL; - n_homing_locate_cycle = 0; // don't do a second touch cycle + ganged_mode = SQUARING_MODE_DUAL; + n_homing_locate_cycle = 0; // don't do a second touch cycle limits_go_home(HOMING_CYCLE_2); - ganged_mode = SQUARING_MODE_A; - n_homing_locate_cycle = N_HOMING_LOCATE_CYCLE; // restore to default value + ganged_mode = SQUARING_MODE_A; + n_homing_locate_cycle = N_HOMING_LOCATE_CYCLE; // restore to default value limits_go_home(HOMING_CYCLE_2); ganged_mode = SQUARING_MODE_B; limits_go_home(HOMING_CYCLE_2); - ganged_mode = SQUARING_MODE_DUAL; // always return to dual + ganged_mode = SQUARING_MODE_DUAL; // always return to dual } #endif #ifdef HOMING_CYCLE_3 @@ -318,15 +329,15 @@ void mc_homing_cycle(uint8_t cycle_mask) { limits_go_home(HOMING_CYCLE_5); // Homing cycle 5 #endif } - protocol_execute_realtime(); // Check for reset and set system abort. - if (sys.abort) { - return; // Did not complete. Alarm state set by mc_alarm. + protocol_execute_realtime(); // Check for reset and set system abort. + if (sys.abort) { + return; // Did not complete. Alarm state set by mc_alarm. } // Homing cycle complete! Setup system for normal operation. // ------------------------------------------------------------------------------------- // Sync gcode parser and planner positions to homed position. gc_sync_position(); - plan_sync_position(); + plan_sync_position(); #ifdef USE_KINEMATICS // This give kinematics a chance to do something after normal homing kinematics_post_homing(); @@ -335,27 +346,28 @@ void mc_homing_cycle(uint8_t cycle_mask) { limits_init(); } - // Perform tool length probe cycle. Requires probe switch. // NOTE: Upon probe failure, the program will be stopped and placed into ALARM state. uint8_t mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t parser_flags) { // TODO: Need to update this cycle so it obeys a non-auto cycle start. - if (sys.state == STATE_CHECK_MODE) return (GC_PROBE_CHECK_MODE); + if (sys.state == STATE_CHECK_MODE) + return (GC_PROBE_CHECK_MODE); // Finish all queued commands and empty planner buffer before starting probe cycle. protocol_buffer_synchronize(); - if (sys.abort) return (GC_PROBE_ABORT); // Return if system reset has been issued. + if (sys.abort) + return (GC_PROBE_ABORT); // Return if system reset has been issued. // Initialize probing control variables uint8_t is_probe_away = bit_istrue(parser_flags, GC_PARSER_PROBE_IS_AWAY); - uint8_t is_no_error = bit_istrue(parser_flags, GC_PARSER_PROBE_IS_NO_ERROR); - sys.probe_succeeded = false; // Re-initialize probe history before beginning cycle. + uint8_t is_no_error = bit_istrue(parser_flags, GC_PARSER_PROBE_IS_NO_ERROR); + sys.probe_succeeded = false; // Re-initialize probe history before beginning cycle. probe_configure_invert_mask(is_probe_away); // After syncing, check if probe is already triggered. If so, halt and issue alarm. // NOTE: This probe initialization error applies to all probing cycles. - if (probe_get_state()) { // Check probe pin state. + if (probe_get_state()) { // Check probe pin state. system_set_exec_alarm(EXEC_ALARM_PROBE_FAIL_INITIAL); protocol_execute_realtime(); - probe_configure_invert_mask(false); // Re-initialize invert mask before returning. - return (GC_PROBE_FAIL_INIT); // Nothing else to do but bail. + probe_configure_invert_mask(false); // Re-initialize invert mask before returning. + return (GC_PROBE_FAIL_INIT); // Nothing else to do but bail. } // Setup and queue probing motion. Auto cycle-start should not start the cycle. mc_line(target, pl_data); @@ -365,48 +377,54 @@ uint8_t mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t parser_ system_set_exec_state_flag(EXEC_CYCLE_START); do { protocol_execute_realtime(); - if (sys.abort) return (GC_PROBE_ABORT); // Check for system abort + if (sys.abort) + return (GC_PROBE_ABORT); // Check for system abort } while (sys.state != STATE_IDLE); // Probing cycle complete! // Set state variables and error out, if the probe failed and cycle with error is enabled. if (sys_probe_state == PROBE_ACTIVE) { - if (is_no_error) memcpy(sys_probe_position, sys_position, sizeof(sys_position)); - else system_set_exec_alarm(EXEC_ALARM_PROBE_FAIL_CONTACT); + if (is_no_error) + memcpy(sys_probe_position, sys_position, sizeof(sys_position)); + else + system_set_exec_alarm(EXEC_ALARM_PROBE_FAIL_CONTACT); } else { - sys.probe_succeeded = true; // Indicate to system the probing cycle completed successfully. + sys.probe_succeeded = true; // Indicate to system the probing cycle completed successfully. } - sys_probe_state = PROBE_OFF; // Ensure probe state monitor is disabled. - probe_configure_invert_mask(false); // Re-initialize invert mask. - protocol_execute_realtime(); // Check and execute run-time commands + sys_probe_state = PROBE_OFF; // Ensure probe state monitor is disabled. + probe_configure_invert_mask(false); // Re-initialize invert mask. + protocol_execute_realtime(); // Check and execute run-time commands // Reset the stepper and planner buffers to remove the remainder of the probe motion. - st_reset(); // Reset step segment buffer. - plan_reset(); // Reset planner buffer. Zero planner positions. Ensure probing motion is cleared. - plan_sync_position(); // Sync planner position to current machine position. + st_reset(); // Reset step segment buffer. + plan_reset(); // Reset planner buffer. Zero planner positions. Ensure probing motion is cleared. + plan_sync_position(); // Sync planner position to current machine position. #ifdef MESSAGE_PROBE_COORDINATES // All done! Output the probe position as message. report_probe_parameters(CLIENT_ALL); #endif - if (sys.probe_succeeded) return (GC_PROBE_FOUND); // Successful probe cycle. - else return (GC_PROBE_FAIL_END); // Failed to trigger probe within travel. With or without error. + if (sys.probe_succeeded) + return (GC_PROBE_FOUND); // Successful probe cycle. + else + return (GC_PROBE_FAIL_END); // Failed to trigger probe within travel. With or without error. } - // Plans and executes the single special motion case for parking. Independent of main planner buffer. // NOTE: Uses the always free planner ring buffer head to store motion parameters for execution. void mc_parking_motion(float* parking_target, plan_line_data_t* pl_data) { - if (sys.abort) return; // Block during abort. + if (sys.abort) + return; // Block during abort. uint8_t plan_status = plan_buffer_line(parking_target, pl_data); if (plan_status) { bit_true(sys.step_control, STEP_CONTROL_EXECUTE_SYS_MOTION); - bit_false(sys.step_control, STEP_CONTROL_END_MOTION); // Allow parking motion to execute, if feed hold is active. - st_parking_setup_buffer(); // Setup step segment buffer for special parking motion case + bit_false(sys.step_control, STEP_CONTROL_END_MOTION); // Allow parking motion to execute, if feed hold is active. + st_parking_setup_buffer(); // Setup step segment buffer for special parking motion case st_prep_buffer(); st_wake_up(); do { protocol_exec_rt_system(); - if (sys.abort) return; + if (sys.abort) + return; } while (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION); - st_parking_restore_buffer(); // Restore step segment buffer to normal run state. + st_parking_restore_buffer(); // Restore step segment buffer to normal run state. } else { bit_false(sys.step_control, STEP_CONTROL_EXECUTE_SYS_MOTION); protocol_exec_rt_system(); @@ -417,12 +435,12 @@ void mc_parking_motion(float* parking_target, plan_line_data_t* pl_data) { void mc_override_ctrl_update(uint8_t override_state) { // Finish all queued commands before altering override control state protocol_buffer_synchronize(); - if (sys.abort) return; + if (sys.abort) + return; sys.override_ctrl = override_state; } #endif - // Method to ready the system to reset by setting the realtime reset command and killing any // active processes in the system. This also checks if a system reset is issued while Grbl // is in a motion state. If so, kills the steppers and sets the system alarm to flag position @@ -434,7 +452,7 @@ void mc_reset() { system_set_exec_state_flag(EXEC_RESET); // Kill spindle and coolant. spindle->stop(); - coolant_stop(); + coolant_stop(); // turn off all digital I/O immediately fast_sys_io_control(0xFF, false); @@ -451,18 +469,18 @@ void mc_reset() { // the steppers enabled by avoiding the go_idle call altogether, unless the motion state is // violated, by which, all bets are off. if ((sys.state & (STATE_CYCLE | STATE_HOMING | STATE_JOG)) || - (sys.step_control & (STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION))) { + (sys.step_control & (STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION))) { if (sys.state == STATE_HOMING) { - if (!sys_rt_exec_alarm) system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_RESET); - } else system_set_exec_alarm(EXEC_ALARM_ABORT_CYCLE); - st_go_idle(); // Force kill steppers. Position has likely been lost. + if (!sys_rt_exec_alarm) + system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_RESET); + } else + system_set_exec_alarm(EXEC_ALARM_ABORT_CYCLE); + st_go_idle(); // Force kill steppers. Position has likely been lost. } - ganged_mode = SQUARING_MODE_DUAL; // in case an error occurred during squaring + ganged_mode = SQUARING_MODE_DUAL; // in case an error occurred during squaring #ifdef USE_I2S_OUT_STREAM i2s_out_reset(); #endif } } - - diff --git a/Grbl_Esp32/motion_control.h b/Grbl_Esp32/motion_control.h index d25237ac..398fd780 100644 --- a/Grbl_Esp32/motion_control.h +++ b/Grbl_Esp32/motion_control.h @@ -26,19 +26,17 @@ #include "grbl.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) -#define HOMING_CYCLE_A bit(A_AXIS) -#define HOMING_CYCLE_B bit(B_AXIS) -#define HOMING_CYCLE_C bit(C_AXIS) - +#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) +#define HOMING_CYCLE_A bit(A_AXIS) +#define HOMING_CYCLE_B bit(B_AXIS) +#define HOMING_CYCLE_C bit(C_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 @@ -50,8 +48,15 @@ void mc_line(float* target, plan_line_data_t* pl_data); // 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, - uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc); +void mc_arc(float* target, + plan_line_data_t* pl_data, + float* position, + float* offset, + float radius, + uint8_t axis_0, + uint8_t axis_1, + uint8_t axis_linear, + uint8_t is_clockwise_arc); // Dwell for a specific number of seconds void mc_dwell(float seconds); diff --git a/Grbl_Esp32/nofile.h b/Grbl_Esp32/nofile.h index b363b458..79e869fa 100644 --- a/Grbl_Esp32/nofile.h +++ b/Grbl_Esp32/nofile.h @@ -1,4 +1,5 @@ #pragma once +// clang-format off /* nofile.h - ESP3D data file diff --git a/Grbl_Esp32/notifications_service.cpp b/Grbl_Esp32/notifications_service.cpp index 1a4ee36c..c7d600fa 100644 --- a/Grbl_Esp32/notifications_service.cpp +++ b/Grbl_Esp32/notifications_service.cpp @@ -30,25 +30,25 @@ #include "grbl.h" #ifdef ENABLE_NOTIFICATIONS -#include "notifications_service.h" -#include -#include +# include "notifications_service.h" +# include +# include -#define PUSHOVERTIMEOUT 5000 -#define PUSHOVERSERVER "api.pushover.net" -#define PUSHOVERPORT 443 +# define PUSHOVERTIMEOUT 5000 +# define PUSHOVERSERVER "api.pushover.net" +# define PUSHOVERPORT 443 -#define LINETIMEOUT 5000 -#define LINESERVER "notify-api.line.me" -#define LINEPORT 443 +# define LINETIMEOUT 5000 +# define LINESERVER "notify-api.line.me" +# define LINEPORT 443 -#define EMAILTIMEOUT 5000 +# define EMAILTIMEOUT 5000 NotificationsService notificationsservice; -bool Wait4Answer(WiFiClientSecure& client, const char* linetrigger, const char* expected_answer, uint32_t timeout) { +bool Wait4Answer(WiFiClientSecure& client, const char* linetrigger, const char* expected_answer, uint32_t timeout) { if (client.connected()) { - String answer; + String answer; uint32_t starttimeout = millis(); while (client.connected() && ((millis() - starttimeout) < timeout)) { answer = client.readStringUntil('\n'); @@ -74,11 +74,11 @@ bool Wait4Answer(WiFiClientSecure& client, const char* linetrigger, const char* } NotificationsService::NotificationsService() { - _started = false; + _started = false; _notificationType = 0; - _token1 = ""; - _token1 = ""; - _settings = ""; + _token1 = ""; + _token1 = ""; + _settings = ""; } NotificationsService::~NotificationsService() { end(); @@ -90,33 +90,23 @@ bool NotificationsService::started() { const char* NotificationsService::getTypeString() { switch (_notificationType) { - case ESP_PUSHOVER_NOTIFICATION: - return "Pushover"; - case ESP_EMAIL_NOTIFICATION: - return "Email"; - case ESP_LINE_NOTIFICATION: - return "Line"; - default: - break; + case ESP_PUSHOVER_NOTIFICATION: return "Pushover"; + case ESP_EMAIL_NOTIFICATION: return "Email"; + case ESP_LINE_NOTIFICATION: return "Line"; + default: break; } return "None"; } bool NotificationsService::sendMSG(const char* title, const char* message) { - if (!_started) return false; + if (!_started) + return false; if (!((strlen(title) == 0) && (strlen(message) == 0))) { switch (_notificationType) { - case ESP_PUSHOVER_NOTIFICATION: - return sendPushoverMSG(title, message); - break; - case ESP_EMAIL_NOTIFICATION: - return sendEmailMSG(title, message); - break; - case ESP_LINE_NOTIFICATION : - return sendLineMSG(title, message); - break; - default: - break; + case ESP_PUSHOVER_NOTIFICATION: return sendPushoverMSG(title, message); break; + case ESP_EMAIL_NOTIFICATION: return sendEmailMSG(title, message); break; + case ESP_LINE_NOTIFICATION: return sendLineMSG(title, message); break; + default: break; } } return false; @@ -124,9 +114,9 @@ bool NotificationsService::sendMSG(const char* title, const char* message) { //Messages are currently limited to 1024 4-byte UTF-8 characters //but we do not do any check bool NotificationsService::sendPushoverMSG(const char* title, const char* message) { - String data; - String postcmd; - bool res; + String data; + String postcmd; + bool res; WiFiClientSecure Notificationclient; if (!Notificationclient.connect(_serveraddress.c_str(), _port)) { log_d("Error connecting server %s:%d", _serveraddress.c_str(), _port); @@ -136,7 +126,8 @@ bool NotificationsService::sendPushoverMSG(const char* title, const char* messag data = "user="; data += _token1; data += "&token="; - data += _token2;; + data += _token2; + ; data += "&title="; data += title; data += "&message="; @@ -144,14 +135,15 @@ bool NotificationsService::sendPushoverMSG(const char* title, const char* messag data += "&device="; data += wifi_config.Hostname(); //build post query - postcmd = "POST /1/messages.json HTTP/1.1\r\nHost: api.pushover.net\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Length: "; - postcmd += data.length(); - postcmd += "\r\n\r\n"; - postcmd += data; + postcmd = "POST /1/messages.json HTTP/1.1\r\nHost: api.pushover.net\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: " + "ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Length: "; + postcmd += data.length(); + postcmd += "\r\n\r\n"; + postcmd += data; log_d("Query: %s", postcmd.c_str()); //send query Notificationclient.print(postcmd); - res = Wait4Answer(Notificationclient, "{", "\"status\":1", PUSHOVERTIMEOUT); + res = Wait4Answer(Notificationclient, "{", "\"status\":1", PUSHOVERTIMEOUT); Notificationclient.stop(); return res; } @@ -240,9 +232,9 @@ bool NotificationsService::sendEmailMSG(const char* title, const char* message) return true; } bool NotificationsService::sendLineMSG(const char* title, const char* message) { - String data; - String postcmd; - bool res; + String data; + String postcmd; + bool res; WiFiClientSecure Notificationclient; (void)title; if (!Notificationclient.connect(_serveraddress.c_str(), _port)) { @@ -253,24 +245,26 @@ bool NotificationsService::sendLineMSG(const char* title, const char* message) { data = "message="; data += message; //build post query - postcmd = "POST /api/notify HTTP/1.1\r\nHost: notify-api.line.me\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Type: application/x-www-form-urlencoded\r\n"; - postcmd += "Authorization: Bearer "; - postcmd += _token1 + "\r\n"; - postcmd += "Content-Length: "; - postcmd += data.length(); - postcmd += "\r\n\r\n"; - postcmd += data; + postcmd = "POST /api/notify HTTP/1.1\r\nHost: notify-api.line.me\r\nConnection: close\r\nCache-Control: no-cache\r\nUser-Agent: " + "ESP3D\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nContent-Type: " + "application/x-www-form-urlencoded\r\n"; + postcmd += "Authorization: Bearer "; + postcmd += _token1 + "\r\n"; + postcmd += "Content-Length: "; + postcmd += data.length(); + postcmd += "\r\n\r\n"; + postcmd += data; log_d("Query: %s", postcmd.c_str()); //send query Notificationclient.print(postcmd); - res = Wait4Answer(Notificationclient, "{", "\"status\":200", LINETIMEOUT); + res = Wait4Answer(Notificationclient, "{", "\"status\":200", LINETIMEOUT); Notificationclient.stop(); return res; } //Email#serveraddress:port bool NotificationsService::getPortFromSettings() { String tmp = notification_ts->get(); - int pos = tmp.lastIndexOf(':'); + int pos = tmp.lastIndexOf(':'); if (pos == -1) return false; _port = tmp.substring(pos + 1).toInt(); @@ -279,9 +273,9 @@ bool NotificationsService::getPortFromSettings() { } //Email#serveraddress:port bool NotificationsService::getServerAddressFromSettings() { - String tmp = notification_ts->get(); - int pos1 = tmp.indexOf('#'); - int pos2 = tmp.lastIndexOf(':'); + String tmp = notification_ts->get(); + int pos1 = tmp.indexOf('#'); + int pos2 = tmp.lastIndexOf(':'); if ((pos1 == -1) || (pos2 == -1)) return false; //TODO add a check for valid email ? @@ -292,7 +286,7 @@ bool NotificationsService::getServerAddressFromSettings() { //Email#serveraddress:port bool NotificationsService::getEmailFromSettings() { String tmp = notification_ts->get(); - int pos = tmp.indexOf('#'); + int pos = tmp.indexOf('#'); if (pos == -1) return false; _settings = tmp.substring(0, pos); @@ -301,34 +295,31 @@ bool NotificationsService::getEmailFromSettings() { return true; } - bool NotificationsService::begin() { end(); _notificationType = notification_type->get(); switch (_notificationType) { - case 0: //no notification = no error but no start - return true; - case ESP_PUSHOVER_NOTIFICATION: - _token1 = notification_t1->get(); - _token2 = notification_t2->get(); - _port = PUSHOVERPORT; - _serveraddress = PUSHOVERSERVER; - break; - case ESP_LINE_NOTIFICATION: - _token1 = notification_t1->get(); - _port = LINEPORT; - _serveraddress = LINESERVER; - break; - case ESP_EMAIL_NOTIFICATION: - _token1 = base64::encode(notification_t1->get()); - _token2 = base64::encode(notification_t2->get()); - if (!getEmailFromSettings() || !getPortFromSettings() || !getServerAddressFromSettings()) { - return false; - } - break; - default: - return false; - break; + case 0: //no notification = no error but no start + return true; + case ESP_PUSHOVER_NOTIFICATION: + _token1 = notification_t1->get(); + _token2 = notification_t2->get(); + _port = PUSHOVERPORT; + _serveraddress = PUSHOVERSERVER; + break; + case ESP_LINE_NOTIFICATION: + _token1 = notification_t1->get(); + _port = LINEPORT; + _serveraddress = LINESERVER; + break; + case ESP_EMAIL_NOTIFICATION: + _token1 = base64::encode(notification_t1->get()); + _token2 = base64::encode(notification_t2->get()); + if (!getEmailFromSettings() || !getPortFromSettings() || !getServerAddressFromSettings()) { + return false; + } + break; + default: return false; break; } bool res = true; if (WiFi.getMode() != WIFI_STA) @@ -341,18 +332,17 @@ bool NotificationsService::begin() { void NotificationsService::end() { if (!_started) return; - _started = false; + _started = false; _notificationType = 0; - _token1 = ""; - _token1 = ""; - _settings = ""; - _serveraddress = ""; - _port = 0; + _token1 = ""; + _token1 = ""; + _settings = ""; + _serveraddress = ""; + _port = 0; } void NotificationsService::handle() { - if (_started) { - } + if (_started) {} } -#endif //ENABLE_NOTIFICATIONS +#endif //ENABLE_NOTIFICATIONS diff --git a/Grbl_Esp32/notifications_service.h b/Grbl_Esp32/notifications_service.h index 222525a1..266eb54c 100644 --- a/Grbl_Esp32/notifications_service.h +++ b/Grbl_Esp32/notifications_service.h @@ -21,29 +21,30 @@ */ class NotificationsService { - public: +public: NotificationsService(); ~NotificationsService(); - bool begin(); - void end(); - void handle(); - bool sendMSG(const char* title, const char* message); + bool begin(); + void end(); + void handle(); + bool sendMSG(const char* title, const char* message); const char* getTypeString(); - bool started(); - private: - bool _started; - uint8_t _notificationType; - String _token1; - String _token2; - String _settings; - String _serveraddress; + bool started(); + +private: + bool _started; + uint8_t _notificationType; + String _token1; + String _token2; + String _settings; + String _serveraddress; uint16_t _port; - bool sendPushoverMSG(const char* title, const char* message); - bool sendEmailMSG(const char* title, const char* message); - bool sendLineMSG(const char* title, const char* message); - bool getPortFromSettings(); - bool getServerAddressFromSettings(); - bool getEmailFromSettings(); + bool sendPushoverMSG(const char* title, const char* message); + bool sendEmailMSG(const char* title, const char* message); + bool sendLineMSG(const char* title, const char* message); + bool getPortFromSettings(); + bool getServerAddressFromSettings(); + bool getEmailFromSettings(); }; extern NotificationsService notificationsservice; diff --git a/Grbl_Esp32/nuts_bolts.cpp b/Grbl_Esp32/nuts_bolts.cpp index 72e86230..8a03d9dd 100644 --- a/Grbl_Esp32/nuts_bolts.cpp +++ b/Grbl_Esp32/nuts_bolts.cpp @@ -24,10 +24,7 @@ #include "grbl.h" - - - -#define MAX_INT_DIGITS 8 // Maximum number of digits in int32 (and float) +#define MAX_INT_DIGITS 8 // Maximum number of digits in int32 (and float) // 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 @@ -37,7 +34,7 @@ // 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(). uint8_t read_float(const char* line, uint8_t* char_counter, float* float_ptr) { - const char* ptr = line + *char_counter; + const char* ptr = line + *char_counter; unsigned char c; // Grab first character and increment pointer. No spaces assumed in line. c = *ptr++; @@ -45,32 +42,36 @@ uint8_t read_float(const char* line, uint8_t* char_counter, float* float_ptr) { bool isnegative = false; if (c == '-') { isnegative = true; - c = *ptr++; + c = *ptr++; } else if (c == '+') c = *ptr++; // Extract number into fast integer. Track decimal in terms of exponent value. - uint32_t intval = 0; - int8_t exp = 0; - uint8_t ndigit = 0; - bool isdecimal = false; + uint32_t intval = 0; + int8_t exp = 0; + uint8_t ndigit = 0; + bool isdecimal = false; while (1) { c -= '0'; if (c <= 9) { ndigit++; if (ndigit <= MAX_INT_DIGITS) { - if (isdecimal) exp--; - intval = (((intval << 2) + intval) << 1) + c; // intval*10 + c + if (isdecimal) + exp--; + intval = (((intval << 2) + intval) << 1) + c; // intval*10 + c } else { - if (!(isdecimal)) exp++; // Drop overflow digits + if (!(isdecimal)) + exp++; // Drop overflow digits } - } else if (c == (('.' - '0') & 0xff) && !(isdecimal)) + } else if (c == (('.' - '0') & 0xff) && !(isdecimal)) isdecimal = true; else break; c = *ptr++; } // Return if no digits have been read. - if (!ndigit) return (false); ; + if (!ndigit) + return (false); + ; // Convert integer into floating point. float fval; fval = (float)intval; @@ -94,7 +95,7 @@ uint8_t read_float(const char* line, uint8_t* char_counter, float* float_ptr) { *float_ptr = -fval; else *float_ptr = fval; - *char_counter = ptr - line - 1; // Set char_counter to next statement + *char_counter = ptr - line - 1; // Set char_counter to next statement return (true); } @@ -106,40 +107,44 @@ void delay_ms(uint16_t ms) { void delay_sec(float seconds, uint8_t mode) { uint16_t i = ceil(1000 / DWELL_TIME_STEP * seconds); while (i-- > 0) { - if (sys.abort) return; + if (sys.abort) + return; if (mode == DELAY_MODE_DWELL) protocol_execute_realtime(); - else { // DELAY_MODE_SYS_SUSPEND + else { // DELAY_MODE_SYS_SUSPEND // Execute rt_system() only to avoid nesting suspend loops. protocol_exec_rt_system(); - if (sys.suspend & SUSPEND_RESTART_RETRACT) return; // Bail, if safety door reopens. + if (sys.suspend & SUSPEND_RESTART_RETRACT) + return; // Bail, if safety door reopens. } - delay(DWELL_TIME_STEP); // Delay DWELL_TIME_STEP increment + delay(DWELL_TIME_STEP); // Delay DWELL_TIME_STEP increment } } // Simple hypotenuse computation function. -float hypot_f(float x, float y) { return (sqrt(x * x + y * y)); } - +float hypot_f(float x, float y) { + return (sqrt(x * x + y * y)); +} float convert_delta_vector_to_unit_vector(float* vector) { uint8_t idx; - float magnitude = 0.0; + float magnitude = 0.0; for (idx = 0; idx < N_AXIS; idx++) { if (vector[idx] != 0.0) magnitude += vector[idx] * vector[idx]; } - magnitude = sqrt(magnitude); + magnitude = sqrt(magnitude); float inv_magnitude = 1.0 / magnitude; - for (idx = 0; idx < N_AXIS; idx++) vector[idx] *= inv_magnitude; + for (idx = 0; idx < N_AXIS; idx++) + vector[idx] *= inv_magnitude; return (magnitude); } float limit_acceleration_by_axis_maximum(float* unit_vec) { uint8_t idx; - float limit_value = SOME_LARGE_VALUE; + float limit_value = SOME_LARGE_VALUE; for (idx = 0; idx < N_AXIS; idx++) { - if (unit_vec[idx] != 0) // Avoid divide by zero. + if (unit_vec[idx] != 0) // Avoid divide by zero. limit_value = MIN(limit_value, fabs(axis_settings[idx]->acceleration->get() / unit_vec[idx])); } // The acceleration setting is stored and displayed in units of mm/sec^2, @@ -151,15 +156,15 @@ float limit_acceleration_by_axis_maximum(float* unit_vec) { float limit_rate_by_axis_maximum(float* unit_vec) { uint8_t idx; - float limit_value = SOME_LARGE_VALUE; + float limit_value = SOME_LARGE_VALUE; for (idx = 0; idx < N_AXIS; idx++) { - if (unit_vec[idx] != 0) // Avoid divide by zero. + if (unit_vec[idx] != 0) // Avoid divide by zero. limit_value = MIN(limit_value, fabs(axis_settings[idx]->max_rate->get() / unit_vec[idx])); } return (limit_value); } -float map_float(float x, float in_min, float in_max, float out_min, float out_max) { // DrawBot_Badge +float map_float(float x, float in_min, float in_max, float out_min, float out_max) { // DrawBot_Badge return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } @@ -167,7 +172,7 @@ uint32_t map_uint32_t(uint32_t x, uint32_t in_min, uint32_t in_max, uint32_t out return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } -float constrain_float(float in, float min, float max) { // DrawBot_Badge +float constrain_float(float in, float min, float max) { // DrawBot_Badge if (in < min) return min; if (in > max) @@ -181,7 +186,5 @@ float mapConstrain(float x, float in_min, float in_max, float out_min, float out } bool char_is_numeric(char value) { - return (value >= '0' && value <='9'); + return (value >= '0' && value <= '9'); } - - diff --git a/Grbl_Esp32/nuts_bolts.h b/Grbl_Esp32/nuts_bolts.h index 58e9cb94..fedce9dd 100644 --- a/Grbl_Esp32/nuts_bolts.h +++ b/Grbl_Esp32/nuts_bolts.h @@ -30,7 +30,7 @@ // Axis array index values. Must start with 0 and be continuous. // Note: You set the number of axes used by changing N_AXIS. // Be sure to define pins or servos in the machine definition file. -#define X_AXIS 0 // Axis indexing value. +#define X_AXIS 0 // Axis indexing value. #define Y_AXIS 1 #define Z_AXIS 2 #define A_AXIS 3 @@ -40,8 +40,8 @@ #define MAX_AXES 6 #define MAX_GANGED 2 -#define PRIMARY_MOTOR 0 -#define GANGED_MOTOR 1 +#define PRIMARY_MOTOR 0 +#define GANGED_MOTOR 1 #define X2_AXIS (X_AXIS + MAX_AXES) #define Y2_AXIS (Y_AXIS + MAX_AXES) @@ -52,34 +52,32 @@ // 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 - - +#define A_MOTOR X_AXIS // Must be X_AXIS +#define B_MOTOR Y_AXIS // Must be Y_AXIS // Conversions #define MM_PER_INCH (25.40) #define INCH_PER_MM (0.0393701) -#define TICKS_PER_MICROSECOND (F_STEPPER_TIMER/1000000) // Different from AVR version +#define TICKS_PER_MICROSECOND (F_STEPPER_TIMER / 1000000) // Different from AVR version -#define DELAY_MODE_DWELL 0 +#define DELAY_MODE_DWELL 0 #define DELAY_MODE_SYS_SUSPEND 1 // Useful macros #define clear_vector(a) memset(a, 0, sizeof(a)) -#define clear_vector_float(a) memset(a, 0.0, sizeof(float)*N_AXIS) +#define clear_vector_float(a) memset(a, 0.0, sizeof(float) * N_AXIS) // #define clear_vector_long(a) memset(a, 0.0, sizeof(long)*N_AXIS) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) // changed to upper case to remove conflicts with other libraries -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) // changed to upper case to remove conflicts with other libraries -#define isequal_position_vector(a,b) !(memcmp(a, b, sizeof(float)*N_AXIS)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) // changed to upper case to remove conflicts with other libraries +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) // changed to upper case to remove conflicts with other libraries +#define isequal_position_vector(a, b) !(memcmp(a, b, sizeof(float) * N_AXIS)) // Bit field and masking macros //Arduino.h:104:0: note: this is the location of the previous definition //#define bit(n) (1 << n) -#define bit_true(x,mask) (x) |= (mask) -#define bit_false(x,mask) (x) &= ~(mask) -#define bit_istrue(x,mask) ((x & mask) != 0) -#define bit_isfalse(x,mask) ((x & mask) == 0) +#define bit_true(x, mask) (x) |= (mask) +#define bit_false(x, mask) (x) &= ~(mask) +#define bit_istrue(x, mask) ((x & mask) != 0) +#define bit_isfalse(x, mask) ((x & mask) == 0) // 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 @@ -99,13 +97,16 @@ float convert_delta_vector_to_unit_vector(float* vector); float limit_acceleration_by_axis_maximum(float* unit_vec); float limit_rate_by_axis_maximum(float* unit_vec); -float mapConstrain(float x, float in_min, float in_max, float out_min, float out_max); -float map_float(float x, float in_min, float in_max, float out_min, float out_max); +float mapConstrain(float x, float in_min, float in_max, float out_min, float out_max); +float map_float(float x, float in_min, float in_max, float out_min, float out_max); uint32_t map_uint32_t(uint32_t x, uint32_t in_min, uint32_t in_max, uint32_t out_min, uint32_t out_max); -float constrain_float(float in, float min, float max); -bool char_is_numeric(char value); -char* trim(char* value); +float constrain_float(float in, float min, float max); +bool char_is_numeric(char value); +char* trim(char* value); -template void swap(T& a, T& b) { - T c(a); a = b; b = c; +template +void swap(T& a, T& b) { + T c(a); + a = b; + b = c; } diff --git a/Grbl_Esp32/planner.cpp b/Grbl_Esp32/planner.cpp index 50d2bcde..faff1d3b 100644 --- a/Grbl_Esp32/planner.cpp +++ b/Grbl_Esp32/planner.cpp @@ -24,42 +24,40 @@ */ #include "grbl.h" -#include // PSoc Required for labs - +#include // PSoc Required for labs static plan_block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instructions -static uint8_t block_buffer_tail; // Index of the block to process now -static uint8_t block_buffer_head; // Index of the next block to be pushed -static uint8_t next_buffer_head; // Index of the next buffer head -static uint8_t block_buffer_planned; // Index of the optimally planned block +static uint8_t block_buffer_tail; // Index of the block to process now +static uint8_t block_buffer_head; // Index of the next block to be pushed +static uint8_t next_buffer_head; // Index of the next buffer head +static uint8_t block_buffer_planned; // Index of the optimally planned block // Define planner variables typedef struct { - int32_t position[N_AXIS]; // The planner position of the tool in absolute steps. Kept separate + 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 + 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; static planner_t pl; - // Returns the index of the next block in the ring buffer. Also called by stepper segment buffer. uint8_t plan_next_block_index(uint8_t block_index) { block_index++; - if (block_index == BLOCK_BUFFER_SIZE) block_index = 0; + if (block_index == BLOCK_BUFFER_SIZE) + block_index = 0; return (block_index); } - // Returns the index of the previous block in the ring buffer static uint8_t plan_prev_block_index(uint8_t block_index) { - if (block_index == 0) block_index = BLOCK_BUFFER_SIZE; + if (block_index == 0) + block_index = BLOCK_BUFFER_SIZE; block_index--; return (block_index); } - /* PLANNER SPEED DEFINITION +--------+ <- current->nominal_speed / \ @@ -129,26 +127,29 @@ static void planner_recalculate() { // Initialize block index to the last block in the planner buffer. uint8_t block_index = plan_prev_block_index(block_buffer_head); // Bail. Can't do anything with one only one plan-able block. - if (block_index == block_buffer_planned) return; + if (block_index == block_buffer_planned) + return; // Reverse Pass: Coarsely maximize all possible deceleration curves back-planning from the last // block in buffer. Cease planning when the last optimal planned or tail pointer is reached. // NOTE: Forward pass will later refine and correct the reverse pass to create an optimal plan. - float entry_speed_sqr; + float entry_speed_sqr; plan_block_t* next; plan_block_t* current = &block_buffer[block_index]; // Calculate maximum entry speed for last block in buffer, where the exit speed is always zero. current->entry_speed_sqr = MIN(current->max_entry_speed_sqr, 2 * current->acceleration * current->millimeters); - block_index = plan_prev_block_index(block_index); - if (block_index == block_buffer_planned) { // Only two plannable blocks in buffer. Reverse pass complete. + block_index = plan_prev_block_index(block_index); + if (block_index == block_buffer_planned) { // Only two plannable blocks in buffer. Reverse pass complete. // Check if the first block is the tail. If so, notify stepper to update its current parameters. - if (block_index == block_buffer_tail) st_update_plan_block_parameters(); - } else { // Three or more plan-able blocks + if (block_index == block_buffer_tail) + st_update_plan_block_parameters(); + } else { // Three or more plan-able blocks while (block_index != block_buffer_planned) { - next = current; - current = &block_buffer[block_index]; + next = current; + current = &block_buffer[block_index]; block_index = plan_prev_block_index(block_index); // Check if next block is the tail block(=planned block). If so, update current stepper parameters. - if (block_index == block_buffer_tail) st_update_plan_block_parameters(); + if (block_index == block_buffer_tail) + st_update_plan_block_parameters(); // Compute maximum entry speed decelerating over the current block from its exit speed. if (current->entry_speed_sqr != current->max_entry_speed_sqr) { entry_speed_sqr = next->entry_speed_sqr + 2 * current->acceleration * current->millimeters; @@ -161,11 +162,11 @@ static void planner_recalculate() { } // Forward Pass: Forward plan the acceleration curve from the planned pointer onward. // Also scans for optimal plan breakpoints and appropriately updates the planned pointer. - next = &block_buffer[block_buffer_planned]; // Begin at buffer planned pointer + next = &block_buffer[block_buffer_planned]; // Begin at buffer planned pointer block_index = plan_next_block_index(block_buffer_planned); while (block_index != block_buffer_head) { current = next; - next = &block_buffer[block_index]; + next = &block_buffer[block_index]; // Any acceleration detected in the forward pass automatically moves the optimal planned // pointer forward, since everything before this is all optimal. In other words, nothing // can improve the plan from the buffer tail to the planned pointer by logic. @@ -173,117 +174,118 @@ static void planner_recalculate() { entry_speed_sqr = current->entry_speed_sqr + 2 * current->acceleration * current->millimeters; // If true, current block is full-acceleration and we can move the planned pointer forward. if (entry_speed_sqr < next->entry_speed_sqr) { - next->entry_speed_sqr = entry_speed_sqr; // Always <= max_entry_speed_sqr. Backward pass sets this. - block_buffer_planned = block_index; // Set optimal plan pointer. + next->entry_speed_sqr = entry_speed_sqr; // Always <= max_entry_speed_sqr. Backward pass sets this. + block_buffer_planned = block_index; // Set optimal plan pointer. } } // Any block set at its maximum entry speed also creates an optimal plan up to this // point in the buffer. When the plan is bracketed by either the beginning of the // buffer and a maximum entry speed or two maximum entry speeds, every block in between // cannot logically be further improved. Hence, we don't have to recompute them anymore. - if (next->entry_speed_sqr == next->max_entry_speed_sqr) block_buffer_planned = block_index; + if (next->entry_speed_sqr == next->max_entry_speed_sqr) + block_buffer_planned = block_index; block_index = plan_next_block_index(block_index); } } - void plan_reset() { - memset(&pl, 0, sizeof(planner_t)); // Clear planner struct + memset(&pl, 0, sizeof(planner_t)); // Clear planner struct plan_reset_buffer(); } - void plan_reset_buffer() { - block_buffer_tail = 0; - block_buffer_head = 0; // Empty = tail - next_buffer_head = 1; // plan_next_block_index(block_buffer_head) - block_buffer_planned = 0; // = block_buffer_tail; + block_buffer_tail = 0; + block_buffer_head = 0; // Empty = tail + next_buffer_head = 1; // plan_next_block_index(block_buffer_head) + block_buffer_planned = 0; // = block_buffer_tail; } - void plan_discard_current_block() { - if (block_buffer_head != block_buffer_tail) { // Discard non-empty buffer. + if (block_buffer_head != block_buffer_tail) { // Discard non-empty buffer. uint8_t block_index = plan_next_block_index(block_buffer_tail); // Push block_buffer_planned pointer, if encountered. - if (block_buffer_tail == block_buffer_planned) block_buffer_planned = block_index; + if (block_buffer_tail == block_buffer_planned) + block_buffer_planned = block_index; block_buffer_tail = block_index; } } - // Returns address of planner buffer block used by system motions. Called by segment generator. plan_block_t* plan_get_system_motion_block() { return (&block_buffer[block_buffer_head]); } - // Returns address of first planner block, if available. Called by various main program functions. plan_block_t* plan_get_current_block() { - if (block_buffer_head == block_buffer_tail) return (NULL); // Buffer empty + if (block_buffer_head == block_buffer_tail) + return (NULL); // Buffer empty return (&block_buffer[block_buffer_tail]); } - float plan_get_exec_block_exit_speed_sqr() { uint8_t block_index = plan_next_block_index(block_buffer_tail); - if (block_index == block_buffer_head) return (0.0); + if (block_index == block_buffer_head) + return (0.0); return (block_buffer[block_index].entry_speed_sqr); } - // Returns the availability status of the block ring buffer. True, if full. uint8_t plan_check_full_buffer() { - if (block_buffer_tail == next_buffer_head) return (true); + if (block_buffer_tail == next_buffer_head) + return (true); return (false); } - // Computes and returns block nominal speed based on running condition and override values. // NOTE: All system motion commands, such as homing/parking, are not subject to overrides. float plan_compute_profile_nominal_speed(plan_block_t* block) { float nominal_speed = block->programmed_rate; - if (block->condition & PL_COND_FLAG_RAPID_MOTION) nominal_speed *= (0.01 * sys.r_override); + if (block->condition & PL_COND_FLAG_RAPID_MOTION) + nominal_speed *= (0.01 * sys.r_override); else { - if (!(block->condition & PL_COND_FLAG_NO_FEED_OVERRIDE)) nominal_speed *= (0.01 * sys.f_override); - if (nominal_speed > block->rapid_rate) nominal_speed = block->rapid_rate; + if (!(block->condition & PL_COND_FLAG_NO_FEED_OVERRIDE)) + nominal_speed *= (0.01 * sys.f_override); + if (nominal_speed > block->rapid_rate) + nominal_speed = block->rapid_rate; } - if (nominal_speed > MINIMUM_FEED_RATE) return (nominal_speed); + if (nominal_speed > MINIMUM_FEED_RATE) + return (nominal_speed); return (MINIMUM_FEED_RATE); } - // Computes and updates the max entry speed (sqr) of the block, based on the minimum of the junction's // previous and current nominal speeds and max junction speed. static void plan_compute_profile_parameters(plan_block_t* block, float nominal_speed, float prev_nominal_speed) { // Compute the junction maximum entry based on the minimum of the junction speed and neighboring nominal speeds. - if (nominal_speed > prev_nominal_speed) block->max_entry_speed_sqr = prev_nominal_speed * prev_nominal_speed; - else block->max_entry_speed_sqr = nominal_speed * nominal_speed; - if (block->max_entry_speed_sqr > block->max_junction_speed_sqr) block->max_entry_speed_sqr = block->max_junction_speed_sqr; + if (nominal_speed > prev_nominal_speed) + block->max_entry_speed_sqr = prev_nominal_speed * prev_nominal_speed; + else + block->max_entry_speed_sqr = nominal_speed * nominal_speed; + if (block->max_entry_speed_sqr > block->max_junction_speed_sqr) + block->max_entry_speed_sqr = block->max_junction_speed_sqr; } - // Re-calculates buffered motions profile parameters upon a motion-based override change. void plan_update_velocity_profile_parameters() { - uint8_t block_index = block_buffer_tail; + uint8_t block_index = block_buffer_tail; plan_block_t* block; - float nominal_speed; - float prev_nominal_speed = SOME_LARGE_VALUE; // Set high for first block nominal speed calculation. + float nominal_speed; + float prev_nominal_speed = SOME_LARGE_VALUE; // Set high for first block nominal speed calculation. while (block_index != block_buffer_head) { - block = &block_buffer[block_index]; + block = &block_buffer[block_index]; nominal_speed = plan_compute_profile_nominal_speed(block); plan_compute_profile_parameters(block, nominal_speed, prev_nominal_speed); prev_nominal_speed = nominal_speed; - block_index = plan_next_block_index(block_index); + block_index = plan_next_block_index(block_index); } - pl.previous_nominal_speed = prev_nominal_speed; // Update prev nominal speed for next incoming block. + pl.previous_nominal_speed = prev_nominal_speed; // Update prev nominal speed for next incoming block. } - uint8_t plan_buffer_line(float* target, plan_line_data_t* pl_data) { // Prepare and initialize new block. Copy relevant pl_data for block execution. plan_block_t* block = &block_buffer[block_buffer_head]; - memset(block, 0, sizeof(plan_block_t)); // Zero all block values. - block->condition = pl_data->condition; + memset(block, 0, sizeof(plan_block_t)); // Zero all block values. + block->condition = pl_data->condition; block->spindle_speed = pl_data->spindle_speed; #ifdef USE_LINE_NUMBERS @@ -291,7 +293,7 @@ uint8_t plan_buffer_line(float* target, plan_line_data_t* pl_data) { #endif // Compute and store initial move distance data. int32_t target_steps[N_AXIS], position_steps[N_AXIS]; - float unit_vec[N_AXIS], delta_mm; + float unit_vec[N_AXIS], delta_mm; uint8_t idx; // Copy position data based on type of motion being planned. if (block->condition & PL_COND_FLAG_SYSTEM_MOTION) { @@ -302,7 +304,8 @@ uint8_t plan_buffer_line(float* target, plan_line_data_t* pl_data) { #else memcpy(position_steps, sys_position, sizeof(sys_position)); #endif - } else memcpy(position_steps, pl.position, sizeof(pl.position)); + } else + memcpy(position_steps, pl.position, sizeof(pl.position)); #ifdef COREXY target_steps[A_MOTOR] = lround(target[A_MOTOR] * axis_settings[A_MOTOR]->steps_per_mm->get()); target_steps[B_MOTOR] = lround(target[B_MOTOR] * axis_settings[B_MOTOR]->steps_per_mm->get()); @@ -320,42 +323,48 @@ uint8_t plan_buffer_line(float* target, plan_line_data_t* pl_data) { } block->step_event_count = MAX(block->step_event_count, block->steps[idx]); if (idx == A_MOTOR) - delta_mm = (target_steps[X_AXIS] - position_steps[X_AXIS] + target_steps[Y_AXIS] - position_steps[Y_AXIS]) / axis_settings[idx]->steps_per_mm->get(); + delta_mm = (target_steps[X_AXIS] - position_steps[X_AXIS] + target_steps[Y_AXIS] - position_steps[Y_AXIS]) / + axis_settings[idx]->steps_per_mm->get(); else if (idx == B_MOTOR) - delta_mm = (target_steps[X_AXIS] - position_steps[X_AXIS] - target_steps[Y_AXIS] + position_steps[Y_AXIS]) / axis_settings[idx]->steps_per_mm->get(); + delta_mm = (target_steps[X_AXIS] - position_steps[X_AXIS] - target_steps[Y_AXIS] + position_steps[Y_AXIS]) / + axis_settings[idx]->steps_per_mm->get(); else delta_mm = (target_steps[idx] - position_steps[idx]) / axis_settings[idx]->steps_per_mm->get(); #else - target_steps[idx] = lround(target[idx] * axis_settings[idx]->steps_per_mm->get()); - block->steps[idx] = labs(target_steps[idx] - position_steps[idx]); + target_steps[idx] = lround(target[idx] * axis_settings[idx]->steps_per_mm->get()); + block->steps[idx] = labs(target_steps[idx] - position_steps[idx]); block->step_event_count = MAX(block->step_event_count, block->steps[idx]); - delta_mm = (target_steps[idx] - position_steps[idx]) / axis_settings[idx]->steps_per_mm->get(); + delta_mm = (target_steps[idx] - position_steps[idx]) / axis_settings[idx]->steps_per_mm->get(); #endif - unit_vec[idx] = delta_mm; // Store unit vector numerator + unit_vec[idx] = delta_mm; // Store unit vector numerator // Set direction bits. Bit enabled always means direction is negative. - if (delta_mm < 0.0) block->direction_bits |= get_direction_pin_mask(idx); + if (delta_mm < 0.0) + block->direction_bits |= get_direction_pin_mask(idx); } // Bail if this is a zero-length block. Highly unlikely to occur. - if (block->step_event_count == 0) return (PLAN_EMPTY_BLOCK); + if (block->step_event_count == 0) + return (PLAN_EMPTY_BLOCK); // Calculate the unit vector of the line move and the block maximum feed rate and acceleration scaled // down such that no individual axes maximum values are exceeded with respect to the line direction. // NOTE: This calculation assumes all axes are orthogonal (Cartesian) and works with ABC-axes, // if they are also orthogonal/independent. Operates on the absolute value of the unit vector. - block->millimeters = convert_delta_vector_to_unit_vector(unit_vec); + block->millimeters = convert_delta_vector_to_unit_vector(unit_vec); block->acceleration = limit_acceleration_by_axis_maximum(unit_vec); - block->rapid_rate = limit_rate_by_axis_maximum(unit_vec); + block->rapid_rate = limit_rate_by_axis_maximum(unit_vec); // Store programmed rate. - if (block->condition & PL_COND_FLAG_RAPID_MOTION) block->programmed_rate = block->rapid_rate; + if (block->condition & PL_COND_FLAG_RAPID_MOTION) + block->programmed_rate = block->rapid_rate; else { block->programmed_rate = pl_data->feed_rate; - if (block->condition & PL_COND_FLAG_INVERSE_TIME) block->programmed_rate *= block->millimeters; + if (block->condition & PL_COND_FLAG_INVERSE_TIME) + block->programmed_rate *= block->millimeters; } // TODO: Need to check this method handling zero junction speeds when starting from rest. if ((block_buffer_head == block_buffer_tail) || (block->condition & PL_COND_FLAG_SYSTEM_MOTION)) { // Initialize block entry speed as zero. Assume it will be starting from rest. Planner will correct this later. // If system motion, the system motion block always is assumed to start from rest and end at a complete stop. - block->entry_speed_sqr = 0.0; - block->max_junction_speed_sqr = 0.0; // Starting from rest. Enforce start from zero velocity. + block->entry_speed_sqr = 0.0; + block->max_junction_speed_sqr = 0.0; // Starting from rest. Enforce start from zero velocity. } else { // Compute maximum allowable entry speed at junction by centripetal acceleration approximation. // Let a circle be tangent to both previous and current path line segments, where the junction @@ -395,9 +404,10 @@ uint8_t plan_buffer_line(float* target, plan_line_data_t* pl_data) { } else { convert_delta_vector_to_unit_vector(junction_unit_vec); float junction_acceleration = limit_acceleration_by_axis_maximum(junction_unit_vec); - float sin_theta_d2 = sqrt(0.5 * (1.0 - junction_cos_theta)); // Trig half angle identity. Always positive. - block->max_junction_speed_sqr = MAX(MINIMUM_JUNCTION_SPEED * MINIMUM_JUNCTION_SPEED, - (junction_acceleration * junction_deviation->get() * sin_theta_d2) / (1.0 - sin_theta_d2)); + float sin_theta_d2 = sqrt(0.5 * (1.0 - junction_cos_theta)); // Trig half angle identity. Always positive. + block->max_junction_speed_sqr = + MAX(MINIMUM_JUNCTION_SPEED * MINIMUM_JUNCTION_SPEED, + (junction_acceleration * junction_deviation->get() * sin_theta_d2) / (1.0 - sin_theta_d2)); } } } @@ -407,11 +417,11 @@ uint8_t plan_buffer_line(float* target, plan_line_data_t* pl_data) { plan_compute_profile_parameters(block, nominal_speed, pl.previous_nominal_speed); pl.previous_nominal_speed = nominal_speed; // Update previous path unit_vector and planner position. - memcpy(pl.previous_unit_vec, unit_vec, sizeof(unit_vec)); // pl.previous_unit_vec[] = unit_vec[] - memcpy(pl.position, target_steps, sizeof(target_steps)); // pl.position[] = target_steps[] + memcpy(pl.previous_unit_vec, unit_vec, sizeof(unit_vec)); // pl.previous_unit_vec[] = unit_vec[] + memcpy(pl.position, target_steps, sizeof(target_steps)); // pl.position[] = target_steps[] // New block is all set. Update buffer head and next buffer head indices. block_buffer_head = next_buffer_head; - next_buffer_head = plan_next_block_index(block_buffer_head); + next_buffer_head = plan_next_block_index(block_buffer_head); // Finish up by recalculating the plan with the new block. planner_recalculate(); } @@ -432,27 +442,26 @@ void plan_sync_position() { else pl.position[idx] = sys_position[idx]; #else - pl.position[idx] = sys_position[idx]; + pl.position[idx] = sys_position[idx]; #endif } } - // Returns the number of available blocks are in the planner buffer. uint8_t plan_get_block_buffer_available() { - if (block_buffer_head >= block_buffer_tail) return ((BLOCK_BUFFER_SIZE - 1) - (block_buffer_head - block_buffer_tail)); + if (block_buffer_head >= block_buffer_tail) + return ((BLOCK_BUFFER_SIZE - 1) - (block_buffer_head - block_buffer_tail)); return ((block_buffer_tail - block_buffer_head - 1)); } - // Returns the number of active blocks are in the planner buffer. // NOTE: Deprecated. Not used unless classic status reports are enabled in config.h uint8_t plan_get_block_buffer_count() { - if (block_buffer_head >= block_buffer_tail) return (block_buffer_head - block_buffer_tail); + if (block_buffer_head >= block_buffer_tail) + return (block_buffer_head - block_buffer_tail); return (BLOCK_BUFFER_SIZE - (block_buffer_tail - block_buffer_head)); } - // Re-initialize buffer plan with a partially completed block, assumed to exist at the buffer tail. // Called after a steppers have come to a complete stop for a feed hold and the cycle is stopped. void plan_cycle_reinitialize() { diff --git a/Grbl_Esp32/planner.h b/Grbl_Esp32/planner.h index d19f88ea..aae40ce7 100644 --- a/Grbl_Esp32/planner.h +++ b/Grbl_Esp32/planner.h @@ -26,11 +26,11 @@ // The number of linear motions that can be in the plan at any give time #ifndef BLOCK_BUFFER_SIZE - #ifdef USE_LINE_NUMBERS - #define BLOCK_BUFFER_SIZE 15 - #else - #define BLOCK_BUFFER_SIZE 16 - #endif +# ifdef USE_LINE_NUMBERS +# define BLOCK_BUFFER_SIZE 15 +# else +# define BLOCK_BUFFER_SIZE 16 +# endif #endif // Returned status message from planner. @@ -38,69 +38,64 @@ #define PLAN_EMPTY_BLOCK false // Define planner data condition flags. Used to denote running conditions of a block. -#define PL_COND_FLAG_RAPID_MOTION bit(0) -#define PL_COND_FLAG_SYSTEM_MOTION bit(1) // Single motion. Circumvents planner state. Used by home/park. -#define PL_COND_FLAG_NO_FEED_OVERRIDE bit(2) // Motion does not honor feed override. -#define PL_COND_FLAG_INVERSE_TIME bit(3) // Interprets feed rate value as inverse time when set. -#define PL_COND_FLAG_SPINDLE_CW bit(4) -#define PL_COND_FLAG_SPINDLE_CCW bit(5) -#define PL_COND_FLAG_COOLANT_FLOOD bit(6) -#define PL_COND_FLAG_COOLANT_MIST bit(7) -#define PL_COND_MOTION_MASK (PL_COND_FLAG_RAPID_MOTION|PL_COND_FLAG_SYSTEM_MOTION|PL_COND_FLAG_NO_FEED_OVERRIDE) -#define PL_COND_ACCESSORY_MASK (PL_COND_FLAG_SPINDLE_CW|PL_COND_FLAG_SPINDLE_CCW|PL_COND_FLAG_COOLANT_FLOOD|PL_COND_FLAG_COOLANT_MIST) - - +#define PL_COND_FLAG_RAPID_MOTION bit(0) +#define PL_COND_FLAG_SYSTEM_MOTION bit(1) // Single motion. Circumvents planner state. Used by home/park. +#define PL_COND_FLAG_NO_FEED_OVERRIDE bit(2) // Motion does not honor feed override. +#define PL_COND_FLAG_INVERSE_TIME bit(3) // Interprets feed rate value as inverse time when set. +#define PL_COND_FLAG_SPINDLE_CW bit(4) +#define PL_COND_FLAG_SPINDLE_CCW bit(5) +#define PL_COND_FLAG_COOLANT_FLOOD bit(6) +#define PL_COND_FLAG_COOLANT_MIST bit(7) +#define PL_COND_MOTION_MASK (PL_COND_FLAG_RAPID_MOTION | PL_COND_FLAG_SYSTEM_MOTION | PL_COND_FLAG_NO_FEED_OVERRIDE) +#define PL_COND_ACCESSORY_MASK (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW | PL_COND_FLAG_COOLANT_FLOOD | PL_COND_FLAG_COOLANT_MIST) // 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 { // 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. - uint8_t direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) + 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. + uint8_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. - uint8_t condition; // Block bitflag variable defining block run conditions. Copied from pl_line_data. + uint8_t condition; // Block bitflag variable defining block run conditions. Copied from pl_line_data. #ifdef USE_LINE_NUMBERS int32_t line_number; // Block line number for real-time reporting. Copied from pl_line_data. #endif // 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 + 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). + 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). - + 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. - float spindle_speed; // Block spindle speed. Copied from pl_line_data. + float spindle_speed; // Block spindle speed. Copied from pl_line_data. //#endif } 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. - uint32_t spindle_speed; // Desired spindle speed through line motion. - uint8_t condition; // Bitflag variable to indicate planner conditions. See defines above. + float feed_rate; // Desired feed rate for line motion. Value is ignored, if rapid motion. + uint32_t spindle_speed; // Desired spindle speed through line motion. + uint8_t condition; // Bitflag variable to indicate planner conditions. See defines above. #ifdef USE_LINE_NUMBERS - int32_t line_number; // Desired line number to report when executing. + int32_t line_number; // Desired line number to report when executing. #endif } plan_line_data_t; - - // Initialize and reset the motion plan subsystem -void plan_reset(); // Reset all -void plan_reset_buffer(); // Reset buffer only. +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 diff --git a/Grbl_Esp32/print.cpp b/Grbl_Esp32/print.cpp deleted file mode 100644 index 8fec2847..00000000 --- a/Grbl_Esp32/print.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - print.c - Functions for formatting output strings - Part of Grbl - - Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC - Copyright (c) 2009-2011 Simen Svale Skogsrud - - 2018 - Bart Dring This file was modifed for use on the ESP32 - CPU. Do not use this with Grbl for atMega328P - - 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 . -*/ - -#include "grbl.h" - - - - -// void printIntegerInBase(unsigned long n, unsigned long base) -// { -// unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. -// unsigned long i = 0; -// -// if (n == 0) { -// serial_write('0'); -// return; -// } -// -// while (n > 0) { -// buf[i++] = n % base; -// n /= base; -// } -// -// for (; i > 0; i--) -// serial_write(buf[i - 1] < 10 ? -// '0' + buf[i - 1] : -// 'A' + buf[i - 1] - 10); -// } - - -// Prints an uint8 variable in base 10. -void print_uint8_base10(uint8_t n) { - uint8_t digit_a = 0; - uint8_t digit_b = 0; - if (n >= 100) { // 100-255 - digit_a = '0' + n % 10; - n /= 10; - } - if (n >= 10) { // 10-99 - digit_b = '0' + n % 10; - n /= 10; - } - serial_write('0' + n); - if (digit_b) serial_write(digit_b); - if (digit_a) serial_write(digit_a); -} - - -// Prints an uint8 variable in base 2 with desired number of desired digits. -void print_uint8_base2_ndigit(uint8_t n, uint8_t digits) { - unsigned char buf[digits]; - uint8_t i = 0; - for (; i < digits; i++) { - buf[i] = n % 2 ; - n /= 2; - } - for (; i > 0; i--) - Serial.print('0' + buf[i - 1]); -} - - -void print_uint32_base10(uint32_t n) { - if (n == 0) { - Serial.print('0'); - return; - } - unsigned char buf[10]; - uint8_t i = 0; - while (n > 0) { - buf[i++] = n % 10; - n /= 10; - } - for (; i > 0; i--) - Serial.print('0' + buf[i - 1]); -} - - -void printInteger(long n) { - if (n < 0) { - Serial.print('-'); - print_uint32_base10(-n); - } else - print_uint32_base10(n); -} - - -// Convert float to string by immediately converting to a long integer, which contains -// more digits than a float. Number of decimal places, which are tracked by a counter, -// may be set by the user. The integer is then efficiently converted to a string. -// NOTE: AVR '%' and '/' integer operations are very efficient. Bitshifting speed-up -// techniques are actually just slightly slower. Found this out the hard way. -void printFloat(float n, uint8_t decimal_places) { - Serial.print(n, decimal_places); -} - - -// Floating value printing handlers for special variables types used in Grbl and are defined -// in the config.h. -// - CoordValue: Handles all position or coordinate values in inches or mm reporting. -// - RateValue: Handles feed rate and current velocity in inches or mm reporting. -void printFloat_CoordValue(float n) { - if (report_inches->get()) - printFloat(n * INCH_PER_MM, N_DECIMAL_COORDVALUE_INCH); - else - printFloat(n, N_DECIMAL_COORDVALUE_MM); -} - -// Debug tool to print free memory in bytes at the called point. -// NOTE: Keep commented unless using. Part of this function always gets compiled in. -// void printFreeMemory() -// { -// extern int __heap_start, *__brkval; -// uint16_t free; // Up to 64k values. -// free = (int) &free - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); -// printInteger((int32_t)free); -// printString(" "); -// } diff --git a/Grbl_Esp32/print.h b/Grbl_Esp32/print.h deleted file mode 100644 index 66f773bd..00000000 --- a/Grbl_Esp32/print.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -/* - print.h - Functions for formatting output strings - Part of Grbl - - Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC - Copyright (c) 2009-2011 Simen Svale Skogsrud - - 2018 - Bart Dring This file was modifed for use on the ESP32 - CPU. Do not use this with Grbl for atMega328P - - 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 . -*/ - -void printString(const char* s); - -void printPgmString(const char* s); - -void printInteger(long n); - -void print_uint32_base10(uint32_t n); - -// Prints an uint8 variable in base 10. -void print_uint8_base10(uint8_t n); - -// Prints an uint8 variable in base 2 with desired number of desired digits. -void print_uint8_base2_ndigit(uint8_t n, uint8_t digits); - -void printFloat(float n, uint8_t decimal_places); - -// Floating value printing handlers for special variables types used in Grbl. -// - CoordValue: Handles all position or coordinate values in inches or mm reporting. -// - RateValue: Handles feed rate and current velocity in inches or mm reporting. -void printFloat_CoordValue(float n); -void printFloat_RateValue(float n); - -// Debug tool to print free memory in bytes at the called point. Not used otherwise. -void printFreeMemory(); diff --git a/Grbl_Esp32/probe.cpp b/Grbl_Esp32/probe.cpp index d53d2bc6..3accfe18 100644 --- a/Grbl_Esp32/probe.cpp +++ b/Grbl_Esp32/probe.cpp @@ -23,31 +23,30 @@ #include "grbl.h" - // Inverts the probe pin state depending on user settings and probing cycle mode. uint8_t probe_invert_mask; - // Probe pin initialization routine. void probe_init() { #ifdef PROBE_PIN -#ifdef DISABLE_PROBE_PIN_PULL_UP +# ifdef DISABLE_PROBE_PIN_PULL_UP pinMode(PROBE_PIN, INPUT); -#else - pinMode(PROBE_PIN, INPUT_PULLUP); // Enable internal pull-up resistors. Normal high operation. -#endif - probe_configure_invert_mask(false); // Initialize invert mask. +# else + pinMode(PROBE_PIN, INPUT_PULLUP); // Enable internal pull-up resistors. Normal high operation. +# endif + probe_configure_invert_mask(false); // Initialize invert mask. #endif } - // Called by probe_init() and the mc_probe() routines. Sets up the probe pin invert mask to // appropriately set the pin logic according to setting for normal-high/normal-low operation // and the probing cycle modes for toward-workpiece/away-from-workpiece. void probe_configure_invert_mask(uint8_t is_probe_away) { - probe_invert_mask = 0; // Initialize as zero. - if (probe_invert->get()) probe_invert_mask ^= PROBE_MASK; - if (is_probe_away) probe_invert_mask ^= PROBE_MASK; + probe_invert_mask = 0; // Initialize as zero. + if (probe_invert->get()) + probe_invert_mask ^= PROBE_MASK; + if (is_probe_away) + probe_invert_mask ^= PROBE_MASK; } // Returns the probe pin state. Triggered = true. Called by gcode parser and probe state monitor. @@ -59,7 +58,6 @@ uint8_t probe_get_state() { #endif } - // Monitors probe pin state and records the system position when detected. Called by the // stepper ISR per ISR tick. // NOTE: This function must be extremely efficient as to not bog down the stepper ISR. diff --git a/Grbl_Esp32/probe.h b/Grbl_Esp32/probe.h index 25be41ae..4a1aec25 100644 --- a/Grbl_Esp32/probe.h +++ b/Grbl_Esp32/probe.h @@ -24,8 +24,8 @@ */ // Values that define the probing state machine. -#define PROBE_OFF 0 // Probing disabled or not in use. (Must be zero.) -#define PROBE_ACTIVE 1 // Actively watching the input pin. +#define PROBE_OFF 0 // Probing disabled or not in use. (Must be zero.) +#define PROBE_ACTIVE 1 // Actively watching the input pin. // Probe pin initialization routine. void probe_init(); diff --git a/Grbl_Esp32/protocol.cpp b/Grbl_Esp32/protocol.cpp index 01d77c66..8fa16e0e 100644 --- a/Grbl_Esp32/protocol.cpp +++ b/Grbl_Esp32/protocol.cpp @@ -26,10 +26,10 @@ static void protocol_exec_rt_suspend(); -static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated. -static char comment[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated. -static uint8_t line_flags = 0; -static uint8_t char_counter = 0; +static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated. +static char comment[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated. +static uint8_t line_flags = 0; +static uint8_t char_counter = 0; static uint8_t comment_char_counter = 0; typedef struct { @@ -41,8 +41,8 @@ client_line_t client_lines[CLIENT_COUNT]; static void empty_line(uint8_t client) { client_line_t* cl = &client_lines[client]; - cl->len = 0; - cl->buffer[0] = '\0'; + cl->len = 0; + cl->buffer[0] = '\0'; } static void empty_lines() { for (uint8_t client = 0; client < CLIENT_COUNT; client++) @@ -68,7 +68,7 @@ err_t add_char_to_line(char c, uint8_t client) { return STATUS_EOL; } cl->buffer[cl->len++] = c; - cl->buffer[cl->len] = '\0'; + cl->buffer[cl->len] = '\0'; return STATUS_OK; } @@ -97,7 +97,7 @@ void protocol_main_loop() { #ifdef CHECK_LIMITS_AT_INIT if (hard_limits->get()) { if (limits_get_state()) { - sys.state = STATE_ALARM; // Ensure alarm state is active. + sys.state = STATE_ALARM; // Ensure alarm state is active. report_feedback_message(MESSAGE_CHECK_LIMITS); } } @@ -107,16 +107,16 @@ void protocol_main_loop() { // Re-initialize the sleep state as an ALARM mode to ensure user homes or acknowledges. if (sys.state & (STATE_ALARM | STATE_SLEEP)) { report_feedback_message(MESSAGE_ALARM_LOCK); - sys.state = STATE_ALARM; // Ensure alarm state is set. + sys.state = STATE_ALARM; // Ensure alarm state is set. } else { // Check if the safety door is open. sys.state = STATE_IDLE; if (system_check_safety_door_ajar()) { bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR); - protocol_execute_realtime(); // Enter safety door mode. Should return as IDLE state. + protocol_execute_realtime(); // Enter safety door mode. Should return as IDLE state. } // All systems go! - system_execute_startup(line); // Execute startup script. + system_execute_startup(line); // Execute startup script. } // --------------------------------------------------------------------------------- // Primary loop! Upon a system abort, this exits back to main() to reset the system. @@ -134,7 +134,7 @@ void protocol_main_loop() { char temp[50]; sd_get_current_filename(temp); grbl_notifyf("SD print done", "%s print is successful", temp); - closeFile(); // close file and clear SD ready/running flags + closeFile(); // close file and clear SD ready/running flags } } #endif @@ -142,40 +142,39 @@ void protocol_main_loop() { // Filtering, if necessary, is done later in gc_execute_line(), so the // filtering is the same with serial and file input. uint8_t client = CLIENT_SERIAL; - char* line; + char* line; for (client = 0; client < CLIENT_COUNT; client++) { while ((c = serial_read(client)) != SERIAL_NO_DATA) { err_t res = add_char_to_line(c, client); switch (res) { - case STATUS_OK: - break; - case STATUS_EOL: - protocol_execute_realtime(); // Runtime command check point. - if (sys.abort) { - return; // Bail to calling function upon system abort - } - line = client_lines[client].buffer; + case STATUS_OK: break; + case STATUS_EOL: + protocol_execute_realtime(); // Runtime command check point. + if (sys.abort) { + return; // Bail to calling function upon system abort + } + line = client_lines[client].buffer; #ifdef REPORT_ECHO_RAW_LINE_RECEIVED - report_echo_line_received(line, client); + report_echo_line_received(line, client); #endif - // auth_level can be upgraded by supplying a password on the command line - report_status_message(execute_line(line, client, LEVEL_GUEST), client); - empty_line(client); - break; - case STATUS_OVERFLOW: - report_status_message(STATUS_OVERFLOW, client); - empty_line(client); - break; + // auth_level can be upgraded by supplying a password on the command line + report_status_message(execute_line(line, client, LEVEL_GUEST), client); + empty_line(client); + break; + case STATUS_OVERFLOW: + report_status_message(STATUS_OVERFLOW, client); + empty_line(client); + break; } - } // while serial read - } // for clients + } // while serial read + } // for clients // If there are no more characters in the serial read buffer to be processed and executed, // this indicates that g-code streaming has either filled the planner buffer or has // completed. In either case, auto-cycle start, if enabled, any queued moves. protocol_auto_cycle_start(); protocol_execute_realtime(); // Runtime command check point. if (sys.abort) { - return; // Bail to main() program loop to reset system. + return; // Bail to main() program loop to reset system. } // check to see if we should disable the stepper drivers ... esp32 work around for disable in main loop. if (stepper_idle) { @@ -186,19 +185,18 @@ void protocol_main_loop() { return; /* Never reached */ } - // Block until all buffered steps are executed or in a cycle state. Works with feed hold // during a synchronize call, if it should happen. Also, waits for clean cycle end. void protocol_buffer_synchronize() { // If system is queued, ensure cycle resumes if the auto start flag is present. protocol_auto_cycle_start(); do { - protocol_execute_realtime(); // Check and execute run-time commands - if (sys.abort) return; // Check for system abort + protocol_execute_realtime(); // Check and execute run-time commands + if (sys.abort) + return; // Check for system abort } while (plan_get_current_block() || (sys.state == STATE_CYCLE)); } - // Auto-cycle start triggers when there is a motion ready to execute and if the main program is not // actively parsing commands. // NOTE: This function is called from the main loop, buffer sync, and mc_line() only and executes @@ -206,12 +204,11 @@ void protocol_buffer_synchronize() { // is finished, single commands), a command that needs to wait for the motions in the buffer to // execute calls a buffer sync, or the planner buffer is full and ready to go. void protocol_auto_cycle_start() { - if (plan_get_current_block() != NULL) { // Check if there are any blocks in the buffer. - system_set_exec_state_flag(EXEC_CYCLE_START); // If so, execute them! + if (plan_get_current_block() != NULL) { // Check if there are any blocks in the buffer. + system_set_exec_state_flag(EXEC_CYCLE_START); // If so, execute them! } } - // This function is the general interface to Grbl's real-time command execution system. It is called // from various check points in the main program, primarily where there may be a while loop waiting // for a buffer to clear space or any point where the execution time from the last check point may @@ -225,26 +222,26 @@ void protocol_auto_cycle_start() { // limit switches, or the main program. void protocol_execute_realtime() { protocol_exec_rt_system(); - if (sys.suspend) protocol_exec_rt_suspend(); + if (sys.suspend) + protocol_exec_rt_suspend(); } - // Executes run-time commands, when required. This function primarily operates as Grbl's state // machine and controls the various real-time features Grbl has to offer. // NOTE: Do not alter this unless you know exactly what you are doing! void protocol_exec_rt_system() { - uint8_t rt_exec; // Temp variable to avoid calling volatile multiple times. - rt_exec = sys_rt_exec_alarm; // Copy volatile sys_rt_exec_alarm. - if (rt_exec) { // Enter only if any bit flag is true + uint8_t rt_exec; // Temp variable to avoid calling volatile multiple times. + rt_exec = sys_rt_exec_alarm; // Copy volatile sys_rt_exec_alarm. + if (rt_exec) { // Enter only if any bit flag is true // System alarm. Everything has shutdown by something that has gone severely wrong. Report // the source of the error to the user. If critical, Grbl disables by entering an infinite // loop until system reset/abort. - sys.state = STATE_ALARM; // Set system alarm state + sys.state = STATE_ALARM; // Set system alarm state report_alarm_message(rt_exec); // Halt everything upon a critical event flag. Currently hard and soft limits flag this. if ((rt_exec == EXEC_ALARM_HARD_LIMIT) || (rt_exec == EXEC_ALARM_SOFT_LIMIT)) { report_feedback_message(MESSAGE_CRITICAL_EVENT); - system_clear_exec_state_flag(EXEC_RESET); // Disable any existing reset + system_clear_exec_state_flag(EXEC_RESET); // Disable any existing reset do { // Block everything, except reset and status reports, until user issues reset or power // cycles. Hard limits typically occur while unattended or not paying attention. Gives @@ -253,14 +250,14 @@ void protocol_exec_rt_system() { // lost, continued streaming could cause a serious crash if by chance it gets executed. } while (bit_isfalse(sys_rt_exec_state, EXEC_RESET)); } - system_clear_exec_alarm(); // Clear alarm + system_clear_exec_alarm(); // Clear alarm } - rt_exec = sys_rt_exec_state; // Copy volatile sys_rt_exec_state. + rt_exec = sys_rt_exec_state; // Copy volatile sys_rt_exec_state. if (rt_exec) { // Execute system abort. if (rt_exec & EXEC_RESET) { sys.abort = true; // Only place this is set true. - return; // Nothing else to do but exit. + return; // Nothing else to do but exit. } // Execute and serial print status if (rt_exec & EXEC_STATUS_REPORT) { @@ -274,28 +271,32 @@ void protocol_exec_rt_system() { if (!(sys.state & (STATE_ALARM | STATE_CHECK_MODE))) { // If in CYCLE or JOG states, immediately initiate a motion HOLD. if (sys.state & (STATE_CYCLE | STATE_JOG)) { - if (!(sys.suspend & (SUSPEND_MOTION_CANCEL | SUSPEND_JOG_CANCEL))) { // Block, if already holding. - st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration. - sys.step_control = STEP_CONTROL_EXECUTE_HOLD; // Initiate suspend state with active flag. - if (sys.state == STATE_JOG) { // Jog cancelled upon any hold event, except for sleeping. - if (!(rt_exec & EXEC_SLEEP)) sys.suspend |= SUSPEND_JOG_CANCEL; + if (!(sys.suspend & (SUSPEND_MOTION_CANCEL | SUSPEND_JOG_CANCEL))) { // Block, if already holding. + st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration. + sys.step_control = STEP_CONTROL_EXECUTE_HOLD; // Initiate suspend state with active flag. + if (sys.state == STATE_JOG) { // Jog cancelled upon any hold event, except for sleeping. + if (!(rt_exec & EXEC_SLEEP)) + sys.suspend |= SUSPEND_JOG_CANCEL; } } } // If IDLE, Grbl is not in motion. Simply indicate suspend state and hold is complete. - if (sys.state == STATE_IDLE) sys.suspend = SUSPEND_HOLD_COMPLETE; + if (sys.state == STATE_IDLE) + sys.suspend = SUSPEND_HOLD_COMPLETE; // Execute and flag a motion cancel with deceleration and return to idle. Used primarily by probing cycle // to halt and cancel the remainder of the motion. if (rt_exec & EXEC_MOTION_CANCEL) { // MOTION_CANCEL only occurs during a CYCLE, but a HOLD and SAFETY_DOOR may been initiated beforehand // to hold the CYCLE. Motion cancel is valid for a single planner block motion only, while jog cancel // will handle and clear multiple planner block motions. - if (!(sys.state & STATE_JOG)) sys.suspend |= SUSPEND_MOTION_CANCEL; // NOTE: State is STATE_CYCLE. + if (!(sys.state & STATE_JOG)) + sys.suspend |= SUSPEND_MOTION_CANCEL; // NOTE: State is STATE_CYCLE. } // Execute a feed hold with deceleration, if required. Then, suspend system. if (rt_exec & EXEC_FEED_HOLD) { // Block SAFETY_DOOR, JOG, and SLEEP states from changing to HOLD state. - if (!(sys.state & (STATE_SAFETY_DOOR | STATE_JOG | STATE_SLEEP))) sys.state = STATE_HOLD; + if (!(sys.state & (STATE_SAFETY_DOOR | STATE_JOG | STATE_SLEEP))) + sys.state = STATE_HOLD; } // Execute a safety door stop with a feed hold and disable spindle/coolant. // NOTE: Safety door differs from feed holds by stopping everything no matter state, disables powered @@ -307,20 +308,21 @@ void protocol_exec_rt_system() { // Check if the safety re-opened during a restore parking motion only. Ignore if // already retracting, parked or in sleep state. if (sys.state == STATE_SAFETY_DOOR) { - if (sys.suspend & SUSPEND_INITIATE_RESTORE) { // Actively restoring + if (sys.suspend & SUSPEND_INITIATE_RESTORE) { // Actively restoring #ifdef PARKING_ENABLE // Set hold and reset appropriate control flags to restart parking sequence. if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) { - st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration. + st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration. sys.step_control = (STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION); sys.suspend &= ~(SUSPEND_HOLD_COMPLETE); - } // else NO_MOTION is active. + } // else NO_MOTION is active. #endif sys.suspend &= ~(SUSPEND_RETRACT_COMPLETE | SUSPEND_INITIATE_RESTORE | SUSPEND_RESTORE_COMPLETE); sys.suspend |= SUSPEND_RESTART_RETRACT; } } - if (sys.state != STATE_SLEEP) sys.state = STATE_SAFETY_DOOR; + if (sys.state != STATE_SLEEP) + sys.state = STATE_SAFETY_DOOR; } // NOTE: This flag doesn't change when the door closes, unlike sys.state. Ensures any parking motions // are executed if the door switch closes and the state returns to HOLD. @@ -328,7 +330,8 @@ void protocol_exec_rt_system() { } } if (rt_exec & EXEC_SLEEP) { - if (sys.state == STATE_ALARM) sys.suspend |= (SUSPEND_RETRACT_COMPLETE | SUSPEND_HOLD_COMPLETE); + if (sys.state == STATE_ALARM) + sys.suspend |= (SUSPEND_RETRACT_COMPLETE | SUSPEND_HOLD_COMPLETE); sys.state = STATE_SLEEP; } system_clear_exec_state_flag((EXEC_MOTION_CANCEL | EXEC_FEED_HOLD | EXEC_SAFETY_DOOR | EXEC_SLEEP)); @@ -341,7 +344,7 @@ void protocol_exec_rt_system() { // Resume door state when parking motion has retracted and door has been closed. if ((sys.state == STATE_SAFETY_DOOR) && !(sys.suspend & SUSPEND_SAFETY_DOOR_AJAR)) { if (sys.suspend & SUSPEND_RESTORE_COMPLETE) { - sys.state = STATE_IDLE; // Set to IDLE to immediately resume the cycle. + sys.state = STATE_IDLE; // Set to IDLE to immediately resume the cycle. } else if (sys.suspend & SUSPEND_RETRACT_COMPLETE) { // Flag to re-energize powered components and restore original position, if disabled by SAFETY_DOOR. // NOTE: For a safety door to resume, the switch must be closed, as indicated by HOLD state, and @@ -354,18 +357,18 @@ void protocol_exec_rt_system() { // Cycle start only when IDLE or when a hold is complete and ready to resume. if ((sys.state == STATE_IDLE) || ((sys.state & STATE_HOLD) && (sys.suspend & SUSPEND_HOLD_COMPLETE))) { if (sys.state == STATE_HOLD && sys.spindle_stop_ovr) { - sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE_CYCLE; // Set to restore in suspend routine and cycle start after. + sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE_CYCLE; // Set to restore in suspend routine and cycle start after. } else { // Start cycle only if queued motions exist in planner buffer and the motion is not canceled. - sys.step_control = STEP_CONTROL_NORMAL_OP; // Restore step control to normal operation + sys.step_control = STEP_CONTROL_NORMAL_OP; // Restore step control to normal operation if (plan_get_current_block() && bit_isfalse(sys.suspend, SUSPEND_MOTION_CANCEL)) { - sys.suspend = SUSPEND_DISABLE; // Break suspend state. - sys.state = STATE_CYCLE; - st_prep_buffer(); // Initialize step segment buffer before beginning cycle. + sys.suspend = SUSPEND_DISABLE; // Break suspend state. + sys.state = STATE_CYCLE; + st_prep_buffer(); // Initialize step segment buffer before beginning cycle. st_wake_up(); - } else { // Otherwise, do nothing. Set and resume IDLE state. - sys.suspend = SUSPEND_DISABLE; // Break suspend state. - sys.state = STATE_IDLE; + } else { // Otherwise, do nothing. Set and resume IDLE state. + sys.suspend = SUSPEND_DISABLE; // Break suspend state. + sys.state = STATE_IDLE; } } } @@ -382,70 +385,84 @@ void protocol_exec_rt_system() { // Hold complete. Set to indicate ready to resume. Remain in HOLD or DOOR states until user // has issued a resume command or reset. plan_cycle_reinitialize(); - if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) sys.suspend |= SUSPEND_HOLD_COMPLETE; + if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) + sys.suspend |= SUSPEND_HOLD_COMPLETE; bit_false(sys.step_control, (STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION)); } else { // Motion complete. Includes CYCLE/JOG/HOMING states and jog cancel/motion cancel/soft limit events. // NOTE: Motion and jog cancel both immediately return to idle after the hold completes. - if (sys.suspend & SUSPEND_JOG_CANCEL) { // For jog cancel, flush buffers and sync positions. + if (sys.suspend & SUSPEND_JOG_CANCEL) { // For jog cancel, flush buffers and sync positions. sys.step_control = STEP_CONTROL_NORMAL_OP; plan_reset(); st_reset(); gc_sync_position(); plan_sync_position(); } - if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { // Only occurs when safety door opens during jog. + if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { // Only occurs when safety door opens during jog. sys.suspend &= ~(SUSPEND_JOG_CANCEL); sys.suspend |= SUSPEND_HOLD_COMPLETE; sys.state = STATE_SAFETY_DOOR; } else { sys.suspend = SUSPEND_DISABLE; - sys.state = STATE_IDLE; + sys.state = STATE_IDLE; } } system_clear_exec_state_flag(EXEC_CYCLE_STOP); } } // Execute overrides. - rt_exec = sys_rt_exec_motion_override; // Copy volatile sys_rt_exec_motion_override + rt_exec = sys_rt_exec_motion_override; // Copy volatile sys_rt_exec_motion_override if (rt_exec) { - system_clear_exec_motion_overrides(); // Clear all motion override flags. - uint8_t new_f_override = sys.f_override; - if (rt_exec & EXEC_FEED_OVR_RESET) new_f_override = DEFAULT_FEED_OVERRIDE; - if (rt_exec & EXEC_FEED_OVR_COARSE_PLUS) new_f_override += FEED_OVERRIDE_COARSE_INCREMENT; - if (rt_exec & EXEC_FEED_OVR_COARSE_MINUS) new_f_override -= FEED_OVERRIDE_COARSE_INCREMENT; - if (rt_exec & EXEC_FEED_OVR_FINE_PLUS) new_f_override += FEED_OVERRIDE_FINE_INCREMENT; - if (rt_exec & EXEC_FEED_OVR_FINE_MINUS) new_f_override -= FEED_OVERRIDE_FINE_INCREMENT; - new_f_override = MIN(new_f_override, MAX_FEED_RATE_OVERRIDE); - new_f_override = MAX(new_f_override, MIN_FEED_RATE_OVERRIDE); + system_clear_exec_motion_overrides(); // Clear all motion override flags. + uint8_t new_f_override = sys.f_override; + if (rt_exec & EXEC_FEED_OVR_RESET) + new_f_override = DEFAULT_FEED_OVERRIDE; + if (rt_exec & EXEC_FEED_OVR_COARSE_PLUS) + new_f_override += FEED_OVERRIDE_COARSE_INCREMENT; + if (rt_exec & EXEC_FEED_OVR_COARSE_MINUS) + new_f_override -= FEED_OVERRIDE_COARSE_INCREMENT; + if (rt_exec & EXEC_FEED_OVR_FINE_PLUS) + new_f_override += FEED_OVERRIDE_FINE_INCREMENT; + if (rt_exec & EXEC_FEED_OVR_FINE_MINUS) + new_f_override -= FEED_OVERRIDE_FINE_INCREMENT; + new_f_override = MIN(new_f_override, MAX_FEED_RATE_OVERRIDE); + new_f_override = MAX(new_f_override, MIN_FEED_RATE_OVERRIDE); uint8_t new_r_override = sys.r_override; - if (rt_exec & EXEC_RAPID_OVR_RESET) new_r_override = DEFAULT_RAPID_OVERRIDE; - if (rt_exec & EXEC_RAPID_OVR_MEDIUM) new_r_override = RAPID_OVERRIDE_MEDIUM; - if (rt_exec & EXEC_RAPID_OVR_LOW) new_r_override = RAPID_OVERRIDE_LOW; + if (rt_exec & EXEC_RAPID_OVR_RESET) + new_r_override = DEFAULT_RAPID_OVERRIDE; + if (rt_exec & EXEC_RAPID_OVR_MEDIUM) + new_r_override = RAPID_OVERRIDE_MEDIUM; + if (rt_exec & EXEC_RAPID_OVR_LOW) + new_r_override = RAPID_OVERRIDE_LOW; if ((new_f_override != sys.f_override) || (new_r_override != sys.r_override)) { - sys.f_override = new_f_override; - sys.r_override = new_r_override; - sys.report_ovr_counter = 0; // Set to report change immediately + sys.f_override = new_f_override; + sys.r_override = new_r_override; + sys.report_ovr_counter = 0; // Set to report change immediately plan_update_velocity_profile_parameters(); plan_cycle_reinitialize(); } } rt_exec = sys_rt_exec_accessory_override; if (rt_exec) { - system_clear_exec_accessory_overrides(); // Clear all accessory override flags. + system_clear_exec_accessory_overrides(); // Clear all accessory override flags. // NOTE: Unlike motion overrides, spindle overrides do not require a planner reinitialization. - uint8_t last_s_override = sys.spindle_speed_ovr; - if (rt_exec & EXEC_SPINDLE_OVR_RESET) last_s_override = DEFAULT_SPINDLE_SPEED_OVERRIDE; - if (rt_exec & EXEC_SPINDLE_OVR_COARSE_PLUS) last_s_override += SPINDLE_OVERRIDE_COARSE_INCREMENT; - if (rt_exec & EXEC_SPINDLE_OVR_COARSE_MINUS) last_s_override -= SPINDLE_OVERRIDE_COARSE_INCREMENT; - if (rt_exec & EXEC_SPINDLE_OVR_FINE_PLUS) last_s_override += SPINDLE_OVERRIDE_FINE_INCREMENT; - if (rt_exec & EXEC_SPINDLE_OVR_FINE_MINUS) last_s_override -= SPINDLE_OVERRIDE_FINE_INCREMENT; + uint8_t last_s_override = sys.spindle_speed_ovr; + if (rt_exec & EXEC_SPINDLE_OVR_RESET) + last_s_override = DEFAULT_SPINDLE_SPEED_OVERRIDE; + if (rt_exec & EXEC_SPINDLE_OVR_COARSE_PLUS) + last_s_override += SPINDLE_OVERRIDE_COARSE_INCREMENT; + if (rt_exec & EXEC_SPINDLE_OVR_COARSE_MINUS) + last_s_override -= SPINDLE_OVERRIDE_COARSE_INCREMENT; + if (rt_exec & EXEC_SPINDLE_OVR_FINE_PLUS) + last_s_override += SPINDLE_OVERRIDE_FINE_INCREMENT; + if (rt_exec & EXEC_SPINDLE_OVR_FINE_MINUS) + last_s_override -= SPINDLE_OVERRIDE_FINE_INCREMENT; last_s_override = MIN(last_s_override, MAX_SPINDLE_SPEED_OVERRIDE); last_s_override = MAX(last_s_override, MIN_SPINDLE_SPEED_OVERRIDE); if (last_s_override != sys.spindle_speed_ovr) { bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); - sys.spindle_speed_ovr = last_s_override; - sys.report_ovr_counter = 0; // Set to report change immediately + sys.spindle_speed_ovr = last_s_override; + sys.report_ovr_counter = 0; // Set to report change immediately // If spinlde is on, tell it the rpm has been overridden if (gc_state.modal.spindle != SPINDLE_DISABLE) spindle->set_rpm(gc_state.spindle_speed); @@ -454,8 +471,10 @@ void protocol_exec_rt_system() { // Spindle stop override allowed only while in HOLD state. // NOTE: Report counters are set in spindle_set_state() when spindle stop is executed. if (sys.state == STATE_HOLD) { - if (!(sys.spindle_stop_ovr)) sys.spindle_stop_ovr = SPINDLE_STOP_OVR_INITIATE; - else if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_ENABLED) sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE; + if (!(sys.spindle_stop_ovr)) + sys.spindle_stop_ovr = SPINDLE_STOP_OVR_INITIATE; + else if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_ENABLED) + sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE; } } // NOTE: Since coolant state always performs a planner sync whenever it changes, the current @@ -479,7 +498,7 @@ void protocol_exec_rt_system() { coolant_state |= COOLANT_MIST_ENABLE; } #endif - coolant_set_state(coolant_state); // Report counter set in coolant_set_state(). + coolant_set_state(coolant_state); // Report counter set in coolant_set_state(). gc_state.modal.coolant = coolant_state; } } @@ -495,7 +514,6 @@ void protocol_exec_rt_system() { st_prep_buffer(); } - // Handles Grbl system suspend procedures, such as feed hold, safety door, and parking motion. // The system will enter this loop, create local variables for suspend tasks, and return to // whatever function that invoked the suspend, such that Grbl resumes normal operation. @@ -504,25 +522,25 @@ void protocol_exec_rt_system() { static void protocol_exec_rt_suspend() { #ifdef PARKING_ENABLE // Declare and initialize parking local variables - float restore_target[N_AXIS]; - float parking_target[N_AXIS]; - float retract_waypoint = PARKING_PULLOUT_INCREMENT; - plan_line_data_t plan_data; + float restore_target[N_AXIS]; + float parking_target[N_AXIS]; + float retract_waypoint = PARKING_PULLOUT_INCREMENT; + plan_line_data_t plan_data; plan_line_data_t* pl_data = &plan_data; memset(pl_data, 0, sizeof(plan_line_data_t)); pl_data->condition = (PL_COND_FLAG_SYSTEM_MOTION | PL_COND_FLAG_NO_FEED_OVERRIDE); -#ifdef USE_LINE_NUMBERS +# ifdef USE_LINE_NUMBERS pl_data->line_number = PARKING_MOTION_LINE_NUMBER; -#endif +# endif #endif plan_block_t* block = plan_get_current_block(); - uint8_t restore_condition; - float restore_spindle_speed; + uint8_t restore_condition; + float restore_spindle_speed; if (block == NULL) { - restore_condition = (gc_state.modal.spindle | gc_state.modal.coolant); + restore_condition = (gc_state.modal.spindle | gc_state.modal.coolant); restore_spindle_speed = gc_state.spindle_speed; } else { - restore_condition = block->condition; + restore_condition = block->condition; restore_spindle_speed = block->spindle_speed; } #ifdef DISABLE_LASER_DURING_HOLD @@ -531,7 +549,8 @@ static void protocol_exec_rt_suspend() { #endif while (sys.suspend) { - if (sys.abort) return; + if (sys.abort) + return; // Block until initial hold is complete and the machine has stopped motion. if (sys.suspend & SUSPEND_HOLD_COMPLETE) { // Parking manager. Handles de/re-energizing, switch state checks, and parking motions for @@ -542,8 +561,8 @@ static void protocol_exec_rt_suspend() { // Ensure any prior spindle stop override is disabled at start of safety door routine. sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; #ifndef PARKING_ENABLE - spindle->set_state(SPINDLE_DISABLE, 0); // De-energize - coolant_set_state(COOLANT_DISABLE); // De-energize + spindle->set_state(SPINDLE_DISABLE, 0); // De-energize + coolant_set_state(COOLANT_DISABLE); // De-energize #else // Get current position and store restore location and spindle retract waypoint. system_convert_array_steps_to_mpos(parking_target, sys_position); @@ -555,41 +574,37 @@ static void protocol_exec_rt_suspend() { // Execute slow pull-out parking retract motion. Parking requires homing enabled, the // current location not exceeding the parking target location, and laser mode disabled. // NOTE: State is will remain DOOR, until the de-energizing and retract is complete. -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL - if (homing_enable->get() && - (parking_target[PARKING_AXIS] < PARKING_TARGET) && - !laser_mode->get() && - (sys.override_ctrl == OVERRIDE_PARKING_MOTION)) { -#else - if (homing_enable->get() && - (parking_target[PARKING_AXIS] < PARKING_TARGET) && - !laser_mode->get()) { -#endif +# ifdef ENABLE_PARKING_OVERRIDE_CONTROL + if (homing_enable->get() && (parking_target[PARKING_AXIS] < PARKING_TARGET) && !laser_mode->get() && + (sys.override_ctrl == OVERRIDE_PARKING_MOTION)) { +# else + if (homing_enable->get() && (parking_target[PARKING_AXIS] < PARKING_TARGET) && !laser_mode->get()) { +# endif // Retract spindle by pullout distance. Ensure retraction motion moves away from // the workpiece and waypoint motion doesn't exceed the parking target location. if (parking_target[PARKING_AXIS] < retract_waypoint) { parking_target[PARKING_AXIS] = retract_waypoint; - pl_data->feed_rate = PARKING_PULLOUT_RATE; - pl_data->condition |= (restore_condition & PL_COND_ACCESSORY_MASK); // Retain accessory state + pl_data->feed_rate = PARKING_PULLOUT_RATE; + pl_data->condition |= (restore_condition & PL_COND_ACCESSORY_MASK); // Retain accessory state pl_data->spindle_speed = restore_spindle_speed; mc_parking_motion(parking_target, pl_data); } // NOTE: Clear accessory state after retract and after an aborted restore motion. - pl_data->condition = (PL_COND_FLAG_SYSTEM_MOTION | PL_COND_FLAG_NO_FEED_OVERRIDE); + pl_data->condition = (PL_COND_FLAG_SYSTEM_MOTION | PL_COND_FLAG_NO_FEED_OVERRIDE); pl_data->spindle_speed = 0.0; - spindle->set_state(SPINDLE_DISABLE, 0); // De-energize - coolant_set_state(COOLANT_DISABLE); // De-energize - // Execute fast parking retract motion to parking target location. + spindle->set_state(SPINDLE_DISABLE, 0); // De-energize + coolant_set_state(COOLANT_DISABLE); // De-energize + // Execute fast parking retract motion to parking target location. if (parking_target[PARKING_AXIS] < PARKING_TARGET) { - parking_target[PARKING_AXIS] = PARKING_TARGET; - pl_data->feed_rate = PARKING_RATE; + parking_target[PARKING_AXIS] = PARKING_TARGET; + pl_data->feed_rate = PARKING_RATE; mc_parking_motion(parking_target, pl_data); } } else { // Parking motion not possible. Just disable the spindle and coolant. // NOTE: Laser mode does not start a parking motion to ensure the laser stops immediately. - spindle->set_state(SPINDLE_DISABLE, 0); // De-energize - coolant_set_state(COOLANT_DISABLE); // De-energize + spindle->set_state(SPINDLE_DISABLE, 0); // De-energize + coolant_set_state(COOLANT_DISABLE); // De-energize } #endif sys.suspend &= ~(SUSPEND_RESTART_RETRACT); @@ -598,16 +613,17 @@ static void protocol_exec_rt_suspend() { if (sys.state == STATE_SLEEP) { report_feedback_message(MESSAGE_SLEEP_MODE); // Spindle and coolant should already be stopped, but do it again just to be sure. - spindle->set_state(SPINDLE_DISABLE, 0); // De-energize - coolant_set_state(COOLANT_DISABLE); // De-energize - st_go_idle(); // Disable steppers - while (!(sys.abort)) protocol_exec_rt_system(); // Do nothing until reset. - return; // Abort received. Return to re-initialize. + spindle->set_state(SPINDLE_DISABLE, 0); // De-energize + coolant_set_state(COOLANT_DISABLE); // De-energize + st_go_idle(); // Disable steppers + while (!(sys.abort)) + protocol_exec_rt_system(); // Do nothing until reset. + return; // Abort received. Return to re-initialize. } // Allows resuming from parking/safety door. Actively checks if safety door is closed and ready to resume. if (sys.state == STATE_SAFETY_DOOR) { if (!(system_check_safety_door_ajar())) { - sys.suspend &= ~(SUSPEND_SAFETY_DOOR_AJAR); // Reset door ajar flag to denote ready to resume. + sys.suspend &= ~(SUSPEND_SAFETY_DOOR_AJAR); // Reset door ajar flag to denote ready to resume. } } // Handles parking restore and safety door resume. @@ -615,36 +631,37 @@ static void protocol_exec_rt_suspend() { #ifdef PARKING_ENABLE // Execute fast restore motion to the pull-out position. Parking requires homing enabled. // NOTE: State is will remain DOOR, until the de-energizing and retract is complete. -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL +# ifdef ENABLE_PARKING_OVERRIDE_CONTROL if (homing_enable->get() && !laser_mode->get()) && (sys.override_ctrl == OVERRIDE_PARKING_MOTION)) { -#else +# else if (homing_enable->get() && !laser_mode->get()) { -#endif - // Check to ensure the motion doesn't move below pull-out position. - if (parking_target[PARKING_AXIS] <= PARKING_TARGET) { - parking_target[PARKING_AXIS] = retract_waypoint; - pl_data->feed_rate = PARKING_RATE; - mc_parking_motion(parking_target, pl_data); +# endif + // Check to ensure the motion doesn't move below pull-out position. + if (parking_target[PARKING_AXIS] <= PARKING_TARGET) { + parking_target[PARKING_AXIS] = retract_waypoint; + pl_data->feed_rate = PARKING_RATE; + mc_parking_motion(parking_target, pl_data); + } } - } #endif // Delayed Tasks: Restart spindle and coolant, delay to power-up, then resume cycle. if (gc_state.modal.spindle != SPINDLE_DISABLE) { - // Block if safety door re-opened during prior restore actions. - if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) { + // Block if safety door re-opened during prior restore actions. + if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) { if (laser_mode->get()) { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } else { - spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), (uint32_t)restore_spindle_speed); + spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), + (uint32_t)restore_spindle_speed); delay_sec(SAFETY_DOOR_SPINDLE_DELAY, DELAY_MODE_SYS_SUSPEND); } } } if (gc_state.modal.coolant != COOLANT_DISABLE) { - // Block if safety door re-opened during prior restore actions. - if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) { + // Block if safety door re-opened during prior restore actions. + if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) { // NOTE: Laser mode will honor this delay. An exhaust system is often controlled by this pin. coolant_set_state((restore_condition & (PL_COND_FLAG_COOLANT_FLOOD | PL_COND_FLAG_COOLANT_FLOOD))); delay_sec(SAFETY_DOOR_COOLANT_DELAY, DELAY_MODE_SYS_SUSPEND); @@ -652,27 +669,27 @@ static void protocol_exec_rt_suspend() { } #ifdef PARKING_ENABLE // Execute slow plunge motion from pull-out position to resume position. -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL +# ifdef ENABLE_PARKING_OVERRIDE_CONTROL if (homing_enable->get() && !laser_mode->get()) && (sys.override_ctrl == OVERRIDE_PARKING_MOTION)) { -#else +# else if (homing_enable->get() && !laser_mode->get()) { -#endif - // Block if safety door re-opened during prior restore actions. - if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) { - // Regardless if the retract parking motion was a valid/safe motion or not, the - // restore parking motion should logically be valid, either by returning to the - // original position through valid machine space or by not moving at all. - pl_data->feed_rate = PARKING_PULLOUT_RATE; - pl_data->condition |= (restore_condition & PL_COND_ACCESSORY_MASK); // Restore accessory state - pl_data->spindle_speed = restore_spindle_speed; - mc_parking_motion(restore_target, pl_data); +# endif + // Block if safety door re-opened during prior restore actions. + if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) { + // Regardless if the retract parking motion was a valid/safe motion or not, the + // restore parking motion should logically be valid, either by returning to the + // original position through valid machine space or by not moving at all. + pl_data->feed_rate = PARKING_PULLOUT_RATE; + pl_data->condition |= (restore_condition & PL_COND_ACCESSORY_MASK); // Restore accessory state + pl_data->spindle_speed = restore_spindle_speed; + mc_parking_motion(restore_target, pl_data); + } } - } #endif if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) { - sys.suspend |= SUSPEND_RESTORE_COMPLETE; - system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. + sys.suspend |= SUSPEND_RESTORE_COMPLETE; + system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. } } } @@ -683,10 +700,10 @@ static void protocol_exec_rt_suspend() { // Handles beginning of spindle stop if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_INITIATE) { if (gc_state.modal.spindle != SPINDLE_DISABLE) { - spindle->set_state(SPINDLE_DISABLE, 0); // De-energize - sys.spindle_stop_ovr = SPINDLE_STOP_OVR_ENABLED; // Set stop override state to enabled, if de-energized. + spindle->set_state(SPINDLE_DISABLE, 0); // De-energize + sys.spindle_stop_ovr = SPINDLE_STOP_OVR_ENABLED; // Set stop override state to enabled, if de-energized. } else { - sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state + sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state } // Handles restoring of spindle state } else if (sys.spindle_stop_ovr & (SPINDLE_STOP_OVR_RESTORE | SPINDLE_STOP_OVR_RESTORE_CYCLE)) { @@ -696,18 +713,20 @@ static void protocol_exec_rt_suspend() { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } else - spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), (uint32_t)restore_spindle_speed); + spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), + (uint32_t)restore_spindle_speed); } if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_RESTORE_CYCLE) { system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. } - sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state + sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state } } else { // Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state. // NOTE: STEP_CONTROL_UPDATE_SPINDLE_RPM is automatically reset upon resume in step generator. if (bit_istrue(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM)) { - spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), (uint32_t)restore_spindle_speed); + spindle->set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), + (uint32_t)restore_spindle_speed); bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } } @@ -716,4 +735,3 @@ static void protocol_exec_rt_suspend() { protocol_exec_rt_system(); } } - diff --git a/Grbl_Esp32/protocol.h b/Grbl_Esp32/protocol.h index 674be6a5..86a6a6f2 100644 --- a/Grbl_Esp32/protocol.h +++ b/Grbl_Esp32/protocol.h @@ -31,7 +31,7 @@ // 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 80 +# define LINE_BUFFER_SIZE 80 #endif // Starts Grbl main loop. It handles all incoming characters from the serial port and executes diff --git a/Grbl_Esp32/report.cpp b/Grbl_Esp32/report.cpp index a9b8e697..8f73317e 100644 --- a/Grbl_Esp32/report.cpp +++ b/Grbl_Esp32/report.cpp @@ -54,18 +54,19 @@ EspClass esp; // this is a generic send function that everything should use, so interfaces could be added (Bluetooth, etc) void grbl_send(uint8_t client, const char* text) { - if (client == CLIENT_INPUT) return; + if (client == CLIENT_INPUT) + return; #ifdef ENABLE_BLUETOOTH if (SerialBT.hasClient() && (client == CLIENT_BT || client == CLIENT_ALL)) { SerialBT.print(text); //delay(10); // possible fix for dropped characters } #endif -#if defined (ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_OUT) +#if defined(ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_OUT) if (client == CLIENT_WEBUI || client == CLIENT_ALL) Serial2Socket.write((const uint8_t*)text, strlen(text)); #endif -#if defined (ENABLE_WIFI) && defined(ENABLE_TELNET) +#if defined(ENABLE_WIFI) && defined(ENABLE_TELNET) if (client == CLIENT_TELNET || client == CLIENT_ALL) telnet_server.write((const uint8_t*)text, strlen(text)); #endif @@ -75,9 +76,10 @@ void grbl_send(uint8_t client, const char* text) { // This is a formating version of the grbl_send(CLIENT_ALL,...) function that work like printf void grbl_sendf(uint8_t client, const char* format, ...) { - if (client == CLIENT_INPUT) return; - char loc_buf[64]; - char* temp = loc_buf; + if (client == CLIENT_INPUT) + return; + char loc_buf[64]; + char* temp = loc_buf; va_list arg; va_list copy; va_start(arg, format); @@ -97,10 +99,12 @@ void grbl_sendf(uint8_t client, const char* format, ...) { } // Use to send [MSG:xxxx] Type messages. The level allows messages to be easily suppressed void grbl_msg_sendf(uint8_t client, uint8_t level, const char* format, ...) { - if (client == CLIENT_INPUT) return; - if (level > GRBL_MSG_LEVEL) return; - char loc_buf[100]; - char* temp = loc_buf; + if (client == CLIENT_INPUT) + return; + if (level > GRBL_MSG_LEVEL) + return; + char loc_buf[100]; + char* temp = loc_buf; va_list arg; va_list copy; va_start(arg, format); @@ -127,8 +131,8 @@ void grbl_notify(const char* title, const char* msg) { } void grbl_notifyf(const char* title, const char* format, ...) { - char loc_buf[64]; - char* temp = loc_buf; + char loc_buf[64]; + char* temp = loc_buf; va_list arg; va_list copy; va_start(arg, format); @@ -150,9 +154,9 @@ void grbl_notifyf(const char* title, const char* format, ...) { // formats axis values into a string and returns that string in rpt static void report_util_axis_values(float* axis_value, char* rpt) { uint8_t idx; - char axisVal[20]; - float unit_conv = 1.0; // unit conversion multiplier..default is mm - rpt[0] = '\0'; + char axisVal[20]; + float unit_conv = 1.0; // unit conversion multiplier..default is mm + rpt[0] = '\0'; if (report_inches->get()) unit_conv = 1.0 / MM_PER_INCH; for (idx = 0; idx < N_AXIS; idx++) { @@ -169,19 +173,20 @@ static void report_util_axis_values(float* axis_value, char* rpt) { void get_state(char* foo) { // pad them to same length switch (sys.state) { - case STATE_IDLE: strcpy(foo, " Idle ");; break; - case STATE_CYCLE: strcpy(foo, " Run "); break; - case STATE_HOLD: strcpy(foo, " Hold "); break; - case STATE_HOMING: strcpy(foo, " Home "); break; - case STATE_ALARM: strcpy(foo, " Alarm"); break; - case STATE_CHECK_MODE: strcpy(foo, " Check"); break; - case STATE_SAFETY_DOOR: strcpy(foo, " Door "); break; - default: strcpy(foo, " ? "); break; + case STATE_IDLE: + strcpy(foo, " Idle "); + ; + break; + case STATE_CYCLE: strcpy(foo, " Run "); break; + case STATE_HOLD: strcpy(foo, " Hold "); break; + case STATE_HOMING: strcpy(foo, " Home "); break; + case STATE_ALARM: strcpy(foo, " Alarm"); break; + case STATE_CHECK_MODE: strcpy(foo, " Check"); break; + case STATE_SAFETY_DOOR: strcpy(foo, " Door "); break; + default: strcpy(foo, " ? "); break; } } - - // Handles the primary confirmation protocol response for streaming interfaces and human-feedback. // For every incoming line, this method responds with an 'ok' for a successful command or an // 'error:' to indicate some error event with the line or some critical system error during @@ -190,42 +195,40 @@ void get_state(char* foo) { // responses. void report_status_message(uint8_t status_code, uint8_t client) { switch (status_code) { - case STATUS_OK: // STATUS_OK + case STATUS_OK: // STATUS_OK #ifdef ENABLE_SD_CARD - if (get_sd_state(false) == SDCARD_BUSY_PRINTING) - SD_ready_next = true; // flag so system_execute_line() will send the next line - else - grbl_send(client, "ok\r\n"); + if (get_sd_state(false) == SDCARD_BUSY_PRINTING) + SD_ready_next = true; // flag so system_execute_line() will send the next line + else + grbl_send(client, "ok\r\n"); #else - grbl_send(client, "ok\r\n"); + grbl_send(client, "ok\r\n"); #endif - break; - default: + break; + default: #ifdef ENABLE_SD_CARD - // do we need to stop a running SD job? - if (get_sd_state(false) == SDCARD_BUSY_PRINTING) { - if (status_code == STATUS_GCODE_UNSUPPORTED_COMMAND) { - grbl_sendf(client, "error:%d\r\n", status_code); // most senders seem to tolerate this error and keep on going - grbl_sendf(CLIENT_ALL, "error:%d in SD file at line %d\r\n", status_code, sd_get_current_line_number()); - // don't close file - } else { - grbl_notifyf("SD print error", "Error:%d during SD file at line: %d", status_code, sd_get_current_line_number()); - grbl_sendf(CLIENT_ALL, "error:%d in SD file at line %d\r\n", status_code, sd_get_current_line_number()); - closeFile(); + // do we need to stop a running SD job? + if (get_sd_state(false) == SDCARD_BUSY_PRINTING) { + if (status_code == STATUS_GCODE_UNSUPPORTED_COMMAND) { + grbl_sendf(client, "error:%d\r\n", status_code); // most senders seem to tolerate this error and keep on going + grbl_sendf(CLIENT_ALL, "error:%d in SD file at line %d\r\n", status_code, sd_get_current_line_number()); + // don't close file + } else { + grbl_notifyf("SD print error", "Error:%d during SD file at line: %d", status_code, sd_get_current_line_number()); + grbl_sendf(CLIENT_ALL, "error:%d in SD file at line %d\r\n", status_code, sd_get_current_line_number()); + closeFile(); + } + return; } - return; - } #endif - grbl_sendf(client, "error:%d\r\n", status_code); + grbl_sendf(client, "error:%d\r\n", status_code); } } - - // Prints alarm messages. void report_alarm_message(uint8_t alarm_code) { - grbl_sendf(CLIENT_ALL, "ALARM:%d\r\n", alarm_code); // OK to send to all clients - delay_ms(500); // Force delay to ensure message clears serial write buffer. + grbl_sendf(CLIENT_ALL, "ALARM:%d\r\n", alarm_code); // OK to send to all clients + delay_ms(500); // Force delay to ensure message clears serial write buffer. } // Prints feedback messages. This serves as a centralized method to provide additional @@ -233,40 +236,31 @@ void report_alarm_message(uint8_t alarm_code) { // messages such as setup warnings, switch toggling, and how to exit alarms. // NOTE: For interfaces, messages are always placed within brackets. And if silent mode // is installed, the message number codes are less than zero. -void report_feedback_message(uint8_t message_code) { // OK to send to all clients +void report_feedback_message(uint8_t message_code) { // OK to send to all clients switch (message_code) { - case MESSAGE_CRITICAL_EVENT: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Reset to continue"); break; - case MESSAGE_ALARM_LOCK: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "'$H'|'$X' to unlock"); break; - case MESSAGE_ALARM_UNLOCK: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Caution: Unlocked"); break; - case MESSAGE_ENABLED: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Enabled"); break; - case MESSAGE_DISABLED: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Disabled"); break; - case MESSAGE_SAFETY_DOOR_AJAR: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Check door"); break; - case MESSAGE_CHECK_LIMITS: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Check limits"); break; - case MESSAGE_PROGRAM_END: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Program End"); break; - case MESSAGE_RESTORE_DEFAULTS: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Restoring defaults"); break; - case MESSAGE_SPINDLE_RESTORE: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Restoring spindle");; break; - case MESSAGE_SLEEP_MODE: - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Sleeping"); break; + case MESSAGE_CRITICAL_EVENT: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Reset to continue"); break; + case MESSAGE_ALARM_LOCK: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "'$H'|'$X' to unlock"); break; + case MESSAGE_ALARM_UNLOCK: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Caution: Unlocked"); break; + case MESSAGE_ENABLED: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Enabled"); break; + case MESSAGE_DISABLED: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Disabled"); break; + case MESSAGE_SAFETY_DOOR_AJAR: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Check door"); break; + case MESSAGE_CHECK_LIMITS: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Check limits"); break; + case MESSAGE_PROGRAM_END: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Program End"); break; + case MESSAGE_RESTORE_DEFAULTS: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Restoring defaults"); break; + case MESSAGE_SPINDLE_RESTORE: + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Restoring spindle"); + ; + break; + case MESSAGE_SLEEP_MODE: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Sleeping"); break; #ifdef ENABLE_SD_CARD - case MESSAGE_SD_FILE_QUIT: - grbl_notifyf("SD print canceled", "Reset during SD file at line: %d", sd_get_current_line_number()); - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Reset during SD file at line: %d", sd_get_current_line_number()); - break; + case MESSAGE_SD_FILE_QUIT: + grbl_notifyf("SD print canceled", "Reset during SD file at line: %d", sd_get_current_line_number()); + grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Reset during SD file at line: %d", sd_get_current_line_number()); + break; #endif } } - // Welcome message void report_init_message(uint8_t client) { grbl_send(client, "\r\nGrbl " GRBL_VERSION " ['$' for help]\r\n"); @@ -277,17 +271,15 @@ void report_grbl_help(uint8_t client) { grbl_send(client, "[HLP:$$ $+ $# $S $L $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H $F $E=err ~ ! ? ctrl-x]\r\n"); } - - // Prints current probe parameters. Upon a probe command, these parameters are updated upon a // successful probe or upon a failed probe with the G38.3 without errors command (if supported). // These values are retained until Grbl is power-cycled, whereby they will be re-zeroed. void report_probe_parameters(uint8_t client) { // Report in terms of machine position. float print_position[N_AXIS]; - char probe_rpt[100]; // the probe report we are building here - char temp[60]; - strcpy(probe_rpt, "[PRB:"); // initialize the string with the first characters + char probe_rpt[100]; // the probe report we are building here + char temp[60]; + strcpy(probe_rpt, "[PRB:"); // initialize the string with the first characters // get the machine position and put them into a string and append to the probe report system_convert_array_steps_to_mpos(print_position, sys_probe_position); report_util_axis_values(print_position, temp); @@ -295,18 +287,15 @@ void report_probe_parameters(uint8_t client) { // add the success indicator and add closing characters sprintf(temp, ":%d]\r\n", sys.probe_succeeded); strcat(probe_rpt, temp); - grbl_send(client, probe_rpt); // send the report + grbl_send(client, probe_rpt); // send the report } - - - // Prints Grbl NGC parameters (coordinate offsets, probing) void report_ngc_parameters(uint8_t client) { - float coord_data[N_AXIS]; + float coord_data[N_AXIS]; uint8_t coord_select; - char temp[60]; - char ngc_rpt[500]; + char temp[60]; + char ngc_rpt[500]; ngc_rpt[0] = '\0'; for (coord_select = 0; coord_select <= SETTING_INDEX_NCOORD; coord_select++) { if (!(settings_read_coord_data(coord_select, coord_data))) { @@ -315,23 +304,23 @@ void report_ngc_parameters(uint8_t client) { } strcat(ngc_rpt, "[G"); switch (coord_select) { - case 6: strcat(ngc_rpt, "28"); break; - case 7: strcat(ngc_rpt, "30"); break; - default: - sprintf(temp, "%d", coord_select + 54); - strcat(ngc_rpt, temp); - break; // G54-G59 + case 6: strcat(ngc_rpt, "28"); break; + case 7: strcat(ngc_rpt, "30"); break; + default: + sprintf(temp, "%d", coord_select + 54); + strcat(ngc_rpt, temp); + break; // G54-G59 } strcat(ngc_rpt, ":"); report_util_axis_values(coord_data, temp); strcat(ngc_rpt, temp); strcat(ngc_rpt, "]\r\n"); } - strcat(ngc_rpt, "[G92:"); // Print G92,G92.1 which are not persistent in memory + strcat(ngc_rpt, "[G92:"); // Print G92,G92.1 which are not persistent in memory report_util_axis_values(gc_state.coord_offset, temp); strcat(ngc_rpt, temp); strcat(ngc_rpt, "]\r\n"); - strcat(ngc_rpt, "[TLO:"); // Print tool length offset value + strcat(ngc_rpt, "[TLO:"); // Print tool length offset value if (report_inches->get()) sprintf(temp, "%4.3f]\r\n", gc_state.tool_length_offset * INCH_PER_MM); else @@ -341,8 +330,6 @@ void report_ngc_parameters(uint8_t client) { report_probe_parameters(client); } - - // Print current gcode parser mode state void report_gcode_modes(uint8_t client) { char temp[20]; @@ -366,24 +353,27 @@ void report_gcode_modes(uint8_t client) { if (gc_state.modal.program_flow) { //report_util_gcode_modes_M(); switch (gc_state.modal.program_flow) { - case PROGRAM_FLOW_PAUSED : strcat(modes_rpt, " M0"); //serial_write('0'); break; - // case PROGRAM_FLOW_OPTIONAL_STOP : serial_write('1'); break; // M1 is ignored and not supported. - case PROGRAM_FLOW_COMPLETED_M2 : - case PROGRAM_FLOW_COMPLETED_M30 : - sprintf(temp, " M%d", gc_state.modal.program_flow); - strcat(modes_rpt, temp); - break; + case PROGRAM_FLOW_PAUSED: + strcat(modes_rpt, " M0"); //serial_write('0'); break; + // case PROGRAM_FLOW_OPTIONAL_STOP : serial_write('1'); break; // M1 is ignored and not supported. + case PROGRAM_FLOW_COMPLETED_M2: + case PROGRAM_FLOW_COMPLETED_M30: + sprintf(temp, " M%d", gc_state.modal.program_flow); + strcat(modes_rpt, temp); + break; } } switch (gc_state.modal.spindle) { - case SPINDLE_ENABLE_CW : strcat(modes_rpt, " M3"); break; - case SPINDLE_ENABLE_CCW : strcat(modes_rpt, " M4"); break; - case SPINDLE_DISABLE : strcat(modes_rpt, " M5"); break; + case SPINDLE_ENABLE_CW: strcat(modes_rpt, " M3"); break; + case SPINDLE_ENABLE_CCW: strcat(modes_rpt, " M4"); break; + case SPINDLE_DISABLE: strcat(modes_rpt, " M5"); break; } //report_util_gcode_modes_M(); // optional M7 and M8 should have been dealt with by here - if (gc_state.modal.coolant) { // Note: Multiple coolant states may be active at the same time. - if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_MIST) strcat(modes_rpt, " M7"); - if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_FLOOD) strcat(modes_rpt, " M8"); + if (gc_state.modal.coolant) { // Note: Multiple coolant states may be active at the same time. + if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_MIST) + strcat(modes_rpt, " M7"); + if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_FLOOD) + strcat(modes_rpt, " M8"); } else strcat(modes_rpt, " M9"); @@ -402,15 +392,13 @@ void report_gcode_modes(uint8_t client) { grbl_send(client, modes_rpt); } - - // Prints specified startup line void report_startup_line(uint8_t n, const char* line, uint8_t client) { - grbl_sendf(client, "$N%d=%s\r\n", n, line); // OK to send to all + grbl_sendf(client, "$N%d=%s\r\n", n, line); // OK to send to all } void report_execute_startup_message(const char* line, uint8_t status_code, uint8_t client) { - grbl_sendf(client, ">%s:", line); // OK to send to all + grbl_sendf(client, ">%s:", line); // OK to send to all report_status_message(status_code, client); } @@ -420,10 +408,10 @@ void report_build_info(char* line, uint8_t client) { strcpy(build_info, "[VER:" GRBL_VERSION "." GRBL_VERSION_BUILD ":"); strcat(build_info, line); strcat(build_info, "]\r\n[OPT:"); - strcat(build_info, "V"); // variable spindle..always on now + strcat(build_info, "V"); // variable spindle..always on now strcat(build_info, "N"); #ifdef COOLANT_MIST_PIN - strcat(build_info, "M"); // TODO Need to deal with M8...it could be disabled + strcat(build_info, "M"); // TODO Need to deal with M8...it could be disabled #endif #ifdef COREXY strcat(build_info, "C"); @@ -432,7 +420,7 @@ void report_build_info(char* line, uint8_t client) { strcat(build_info, "P"); #endif #if (defined(HOMING_FORCE_SET_ORIGIN) || defined(HOMING_FORCE_POSITIVE_SPACE)) - strcat(build_info, "Z"); // homing MPOS bahavior is not the default behavior + strcat(build_info, "Z"); // homing MPOS bahavior is not the default behavior #endif #ifdef HOMING_SINGLE_AXIS_COMMANDS strcat(build_info, "H"); @@ -452,36 +440,36 @@ void report_build_info(char* line, uint8_t client) { #ifdef ENABLE_PARKING_OVERRIDE_CONTROL serial_write('R'); #endif -#if defined (ENABLE_WIFI) +#if defined(ENABLE_WIFI) strcat(build_info, "W"); #endif -#ifndef ENABLE_RESTORE_EEPROM_WIPE_ALL // NOTE: Shown when disabled. +#ifndef ENABLE_RESTORE_EEPROM_WIPE_ALL // NOTE: Shown when disabled. strcat(build_info, "*"); #endif -#ifndef ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS // NOTE: Shown when disabled. +#ifndef ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS // NOTE: Shown when disabled. strcat(build_info, "$"); #endif -#ifndef ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS // NOTE: Shown when disabled. +#ifndef ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS // NOTE: Shown when disabled. strcat(build_info, "#"); #endif -#ifndef ENABLE_BUILD_INFO_WRITE_COMMAND // NOTE: Shown when disabled. +#ifndef ENABLE_BUILD_INFO_WRITE_COMMAND // NOTE: Shown when disabled. strcat(build_info, "I"); #endif -#ifndef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE // NOTE: Shown when disabled. +#ifndef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE // NOTE: Shown when disabled. strcat(build_info, "E"); #endif -#ifndef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE // NOTE: Shown when disabled. +#ifndef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE // NOTE: Shown when disabled. strcat(build_info, "W"); #endif // NOTE: Compiled values, like override increments/max/min values, may be added at some point later. // These will likely have a comma delimiter to separate them. strcat(build_info, "]\r\n"); - grbl_send(client, build_info); // ok to send to all + grbl_send(client, build_info); // ok to send to all report_machine_type(client); -#if defined (ENABLE_WIFI) +#if defined(ENABLE_WIFI) grbl_send(client, (char*)wifi_config.info()); #endif -#if defined (ENABLE_BLUETOOTH) +#if defined(ENABLE_BLUETOOTH) grbl_send(client, (char*)bt_config.info()); #endif } @@ -499,53 +487,55 @@ void report_echo_line_received(char* line, uint8_t client) { // especially during g-code programs with fast, short line segments and high frequency reports (5-20Hz). void report_realtime_status(uint8_t client) { uint8_t idx; - int32_t current_position[N_AXIS]; // Copy current state of the system position variable + int32_t current_position[N_AXIS]; // Copy current state of the system position variable memcpy(current_position, sys_position, sizeof(sys_position)); float print_position[N_AXIS]; - char status[200]; - char temp[80]; + char status[200]; + char temp[80]; system_convert_array_steps_to_mpos(print_position, current_position); // Report current machine state and sub-states strcpy(status, "<"); switch (sys.state) { - case STATE_IDLE: strcat(status, "Idle"); break; - case STATE_CYCLE: strcat(status, "Run"); break; - case STATE_HOLD: - if (!(sys.suspend & SUSPEND_JOG_CANCEL)) { - strcat(status, "Hold:"); - if (sys.suspend & SUSPEND_HOLD_COMPLETE) strcat(status, "0"); // Ready to resume - else strcat(status, "1"); // Actively holding - break; - } // Continues to print jog state during jog cancel. - case STATE_JOG: strcat(status, "Jog"); break; - case STATE_HOMING: strcat(status, "Home"); break; - case STATE_ALARM: strcat(status, "Alarm"); break; - case STATE_CHECK_MODE: strcat(status, "Check"); break; - case STATE_SAFETY_DOOR: - strcat(status, "Door:"); - if (sys.suspend & SUSPEND_INITIATE_RESTORE) { - strcat(status, "3"); // Restoring - } else { - if (sys.suspend & SUSPEND_RETRACT_COMPLETE) { - if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { - strcat(status, "1"); // Door ajar - } else - strcat(status, "0"); - // Door closed and ready to resume + case STATE_IDLE: strcat(status, "Idle"); break; + case STATE_CYCLE: strcat(status, "Run"); break; + case STATE_HOLD: + if (!(sys.suspend & SUSPEND_JOG_CANCEL)) { + strcat(status, "Hold:"); + if (sys.suspend & SUSPEND_HOLD_COMPLETE) + strcat(status, "0"); // Ready to resume + else + strcat(status, "1"); // Actively holding + break; + } // Continues to print jog state during jog cancel. + case STATE_JOG: strcat(status, "Jog"); break; + case STATE_HOMING: strcat(status, "Home"); break; + case STATE_ALARM: strcat(status, "Alarm"); break; + case STATE_CHECK_MODE: strcat(status, "Check"); break; + case STATE_SAFETY_DOOR: + strcat(status, "Door:"); + if (sys.suspend & SUSPEND_INITIATE_RESTORE) { + strcat(status, "3"); // Restoring } else { - strcat(status, "2"); // Retracting + if (sys.suspend & SUSPEND_RETRACT_COMPLETE) { + if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { + strcat(status, "1"); // Door ajar + } else + strcat(status, "0"); + // Door closed and ready to resume + } else { + strcat(status, "2"); // Retracting + } } - } - break; - case STATE_SLEEP: strcat(status, "Sleep"); break; + break; + case STATE_SLEEP: strcat(status, "Sleep"); break; } float wco[N_AXIS]; - if (bit_isfalse(status_mask->get(), BITFLAG_RT_STATUS_POSITION_TYPE) || - (sys.report_wco_counter == 0)) { + if (bit_isfalse(status_mask->get(), BITFLAG_RT_STATUS_POSITION_TYPE) || (sys.report_wco_counter == 0)) { for (idx = 0; idx < N_AXIS; idx++) { // Apply work coordinate offsets and tool length offset to current position. wco[idx] = gc_state.coord_system[idx] + gc_state.coord_offset[idx]; - if (idx == TOOL_LENGTH_OFFSET_AXIS) wco[idx] += gc_state.tool_length_offset; + if (idx == TOOL_LENGTH_OFFSET_AXIS) + wco[idx] += gc_state.tool_length_offset; if (bit_isfalse(status_mask->get(), BITFLAG_RT_STATUS_POSITION_TYPE)) print_position[idx] -= wco[idx]; } @@ -565,16 +555,16 @@ void report_realtime_status(uint8_t client) { #ifdef REPORT_FIELD_BUFFER_STATE if (bit_istrue(status_mask->get(), BITFLAG_RT_STATUS_BUFFER_STATE)) { int bufsize = DEFAULTBUFFERSIZE; -#if defined (ENABLE_WIFI) && defined(ENABLE_TELNET) +# if defined(ENABLE_WIFI) && defined(ENABLE_TELNET) if (client == CLIENT_TELNET) bufsize = telnet_server.get_rx_buffer_available(); -#endif //ENABLE_WIFI && ENABLE_TELNET -#if defined(ENABLE_BLUETOOTH) +# endif //ENABLE_WIFI && ENABLE_TELNET +# if defined(ENABLE_BLUETOOTH) if (client == CLIENT_BT) { //TODO FIXME bufsize = 512 - SerialBT.available(); } -#endif //ENABLE_BLUETOOTH +# endif //ENABLE_BLUETOOTH if (client == CLIENT_SERIAL) bufsize = serial_get_rx_buffer_available(CLIENT_SERIAL); sprintf(temp, "|Bf:%d,%d", plan_get_block_buffer_available(), bufsize); @@ -582,7 +572,7 @@ void report_realtime_status(uint8_t client) { } #endif #ifdef USE_LINE_NUMBERS -#ifdef REPORT_FIELD_LINE_NUMBERS +# ifdef REPORT_FIELD_LINE_NUMBERS // Report current line number plan_block_t* cur_block = plan_get_current_block(); if (cur_block != NULL) { @@ -592,79 +582,99 @@ void report_realtime_status(uint8_t client) { strcat(status, temp); } } -#endif +# endif #endif // Report realtime feed speed #ifdef REPORT_FIELD_CURRENT_FEED_SPEED if (report_inches->get()) - sprintf(temp, "|FS:%.1f,%d", st_get_realtime_rate()/ MM_PER_INCH, sys.spindle_speed); + sprintf(temp, "|FS:%.1f,%d", st_get_realtime_rate() / MM_PER_INCH, sys.spindle_speed); else sprintf(temp, "|FS:%.0f,%d", st_get_realtime_rate(), sys.spindle_speed); strcat(status, temp); #endif #ifdef REPORT_FIELD_PIN_STATE - uint8_t lim_pin_state = limits_get_state(); + uint8_t lim_pin_state = limits_get_state(); uint8_t ctrl_pin_state = system_control_get_state(); - uint8_t prb_pin_state = probe_get_state(); + uint8_t prb_pin_state = probe_get_state(); if (lim_pin_state | ctrl_pin_state | prb_pin_state) { strcat(status, "|Pn:"); - if (prb_pin_state) strcat(status, "P"); + if (prb_pin_state) + strcat(status, "P"); if (lim_pin_state) { - if (bit_istrue(lim_pin_state, bit(X_AXIS))) strcat(status, "X"); - if (bit_istrue(lim_pin_state, bit(Y_AXIS))) strcat(status, "Y"); - if (bit_istrue(lim_pin_state, bit(Z_AXIS))) strcat(status, "Z"); -#if (N_AXIS > A_AXIS) - if (bit_istrue(lim_pin_state, bit(A_AXIS))) strcat(status, "A"); -#endif -#if (N_AXIS > B_AXIS) - if (bit_istrue(lim_pin_state, bit(B_AXIS))) strcat(status, "B"); -#endif -#if (N_AXIS > C_AXIS) - if (bit_istrue(lim_pin_state, bit(C_AXIS))) strcat(status, "C"); -#endif + if (bit_istrue(lim_pin_state, bit(X_AXIS))) + strcat(status, "X"); + if (bit_istrue(lim_pin_state, bit(Y_AXIS))) + strcat(status, "Y"); + if (bit_istrue(lim_pin_state, bit(Z_AXIS))) + strcat(status, "Z"); +# if (N_AXIS > A_AXIS) + if (bit_istrue(lim_pin_state, bit(A_AXIS))) + strcat(status, "A"); +# endif +# if (N_AXIS > B_AXIS) + if (bit_istrue(lim_pin_state, bit(B_AXIS))) + strcat(status, "B"); +# endif +# if (N_AXIS > C_AXIS) + if (bit_istrue(lim_pin_state, bit(C_AXIS))) + strcat(status, "C"); +# endif } if (ctrl_pin_state) { -#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN - if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_SAFETY_DOOR)) strcat(status, "D"); -#endif - if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_RESET)) strcat(status, "R"); - if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_FEED_HOLD)) strcat(status, "H"); - if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_CYCLE_START)) strcat(status, "S"); +# ifdef ENABLE_SAFETY_DOOR_INPUT_PIN + if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_SAFETY_DOOR)) + strcat(status, "D"); +# endif + if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_RESET)) + strcat(status, "R"); + if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_FEED_HOLD)) + strcat(status, "H"); + if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_CYCLE_START)) + strcat(status, "S"); } } #endif #ifdef REPORT_FIELD_WORK_COORD_OFFSET - if (sys.report_wco_counter > 0) sys.report_wco_counter--; + if (sys.report_wco_counter > 0) + sys.report_wco_counter--; else { if (sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) { - sys.report_wco_counter = (REPORT_WCO_REFRESH_BUSY_COUNT - 1); // Reset counter for slow refresh - } else sys.report_wco_counter = (REPORT_WCO_REFRESH_IDLE_COUNT - 1); - if (sys.report_ovr_counter == 0) sys.report_ovr_counter = 1; // Set override on next report. + sys.report_wco_counter = (REPORT_WCO_REFRESH_BUSY_COUNT - 1); // Reset counter for slow refresh + } else + sys.report_wco_counter = (REPORT_WCO_REFRESH_IDLE_COUNT - 1); + if (sys.report_ovr_counter == 0) + sys.report_ovr_counter = 1; // Set override on next report. strcat(status, "|WCO:"); report_util_axis_values(wco, temp); strcat(status, temp); } #endif #ifdef REPORT_FIELD_OVERRIDES - if (sys.report_ovr_counter > 0) sys.report_ovr_counter--; + if (sys.report_ovr_counter > 0) + sys.report_ovr_counter--; else { if (sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) { - sys.report_ovr_counter = (REPORT_OVR_REFRESH_BUSY_COUNT - 1); // Reset counter for slow refresh - } else sys.report_ovr_counter = (REPORT_OVR_REFRESH_IDLE_COUNT - 1); + sys.report_ovr_counter = (REPORT_OVR_REFRESH_BUSY_COUNT - 1); // Reset counter for slow refresh + } else + sys.report_ovr_counter = (REPORT_OVR_REFRESH_IDLE_COUNT - 1); sprintf(temp, "|Ov:%d,%d,%d", sys.f_override, sys.r_override, sys.spindle_speed_ovr); strcat(status, temp); - uint8_t sp_state = spindle->get_state(); + uint8_t sp_state = spindle->get_state(); uint8_t cl_state = coolant_get_state(); if (sp_state || cl_state) { strcat(status, "|A:"); - if (sp_state) { // != SPINDLE_STATE_DISABLE - if (sp_state == SPINDLE_STATE_CW) strcat(status, "S"); // CW - else strcat(status, "C"); // CCW + if (sp_state) { // != SPINDLE_STATE_DISABLE + if (sp_state == SPINDLE_STATE_CW) + strcat(status, "S"); // CW + else + strcat(status, "C"); // CCW } - if (cl_state & COOLANT_STATE_FLOOD) strcat(status, "F"); -#ifdef COOLANT_MIST_PIN // TODO Deal with M8 - Flood - if (cl_state & COOLANT_STATE_MIST) strcat(status, "M"); -#endif + if (cl_state & COOLANT_STATE_FLOOD) + strcat(status, "F"); +# ifdef COOLANT_MIST_PIN // TODO Deal with M8 - Flood + if (cl_state & COOLANT_STATE_MIST) + strcat(status, "M"); +# endif } } #endif @@ -692,15 +702,15 @@ void report_realtime_steps() { } void report_gcode_comment(char* comment) { - char msg[80]; + char msg[80]; const uint8_t offset = 4; // ignore "MSG_" part of comment - uint8_t index = offset; + uint8_t index = offset; if (strstr(comment, "MSG")) { while (index < strlen(comment)) { msg[index - offset] = comment[index]; index++; } - msg[index - offset] = 0; // null terminate + msg[index - offset] = 0; // null terminate grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "GCode Comment...%s", msg); } } @@ -709,7 +719,6 @@ void report_machine_type(uint8_t client) { grbl_msg_sendf(client, MSG_LEVEL_INFO, "Using machine:%s", MACHINE_NAME); } - /* Print a message in hex format Ex: report_hex_msg(msg, "Rx:", 6); @@ -725,7 +734,6 @@ void report_hex_msg(char* buf, const char* prefix, int len) { } grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s", report); - } void report_hex_msg(uint8_t* buf, const char* prefix, int len) { @@ -738,24 +746,16 @@ void report_hex_msg(uint8_t* buf, const char* prefix, int len) { } grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s", report); - } char report_get_axis_letter(uint8_t axis) { switch (axis) { - case X_AXIS: - return 'X'; - case Y_AXIS: - return 'Y'; - case Z_AXIS: - return 'Z'; - case A_AXIS: - return 'A'; - case B_AXIS: - return 'B'; - case C_AXIS: - return 'C'; - default: - return '?'; + case X_AXIS: return 'X'; + case Y_AXIS: return 'Y'; + case Z_AXIS: return 'Z'; + case A_AXIS: return 'A'; + case B_AXIS: return 'B'; + case C_AXIS: return 'C'; + default: return '?'; } } diff --git a/Grbl_Esp32/report.h b/Grbl_Esp32/report.h index 3b3e85f4..4f7166ce 100644 --- a/Grbl_Esp32/report.h +++ b/Grbl_Esp32/report.h @@ -61,22 +61,22 @@ #define STATUS_GCODE_MAX_VALUE_EXCEEDED 38 #define STATUS_P_PARAM_MAX_EXCEEDED 39 -#define STATUS_SD_FAILED_MOUNT 60 // SD Failed to mount -#define STATUS_SD_FAILED_READ 61 // SD Failed to read file -#define STATUS_SD_FAILED_OPEN_DIR 62 // SD card failed to open directory -#define STATUS_SD_DIR_NOT_FOUND 63 // SD Card directory not found -#define STATUS_SD_FILE_EMPTY 64 // SD Card directory not found -#define STATUS_SD_FILE_NOT_FOUND 65 // SD Card file not found -#define STATUS_SD_FAILED_OPEN_FILE 66 // SD card failed to open file -#define STATUS_SD_FAILED_BUSY 67 // SD card is busy +#define STATUS_SD_FAILED_MOUNT 60 // SD Failed to mount +#define STATUS_SD_FAILED_READ 61 // SD Failed to read file +#define STATUS_SD_FAILED_OPEN_DIR 62 // SD card failed to open directory +#define STATUS_SD_DIR_NOT_FOUND 63 // SD Card directory not found +#define STATUS_SD_FILE_EMPTY 64 // SD Card directory not found +#define STATUS_SD_FILE_NOT_FOUND 65 // SD Card file not found +#define STATUS_SD_FAILED_OPEN_FILE 66 // SD card failed to open file +#define STATUS_SD_FAILED_BUSY 67 // SD card is busy #define STATUS_SD_FAILED_DEL_DIR 68 #define STATUS_SD_FAILED_DEL_FILE 69 -#define STATUS_BT_FAIL_BEGIN 70 // Bluetooth failed to start +#define STATUS_BT_FAIL_BEGIN 70 // Bluetooth failed to start #define STATUS_WIFI_FAIL_BEGIN 71 // WiFi failed to start -#define STATUS_NUMBER_RANGE 80 // Setting number range problem -#define STATUS_INVALID_VALUE 81 // Setting string problem +#define STATUS_NUMBER_RANGE 80 // Setting number range problem +#define STATUS_INVALID_VALUE 81 // Setting string problem #define STATUS_MESSAGE_FAILED 90 @@ -85,19 +85,19 @@ #define STATUS_AUTHENTICATION_FAILED 110 #define STATUS_EOL 111 -typedef uint8_t err_t; // For status codes -const char* errorString(err_t errorNumber); +typedef uint8_t err_t; // For status codes +const char* errorString(err_t errorNumber); // Define Grbl alarm codes. Valid values (1-255). 0 is reserved. -#define ALARM_HARD_LIMIT_ERROR EXEC_ALARM_HARD_LIMIT -#define ALARM_SOFT_LIMIT_ERROR EXEC_ALARM_SOFT_LIMIT -#define ALARM_ABORT_CYCLE EXEC_ALARM_ABORT_CYCLE -#define ALARM_PROBE_FAIL_INITIAL EXEC_ALARM_PROBE_FAIL_INITIAL -#define ALARM_PROBE_FAIL_CONTACT EXEC_ALARM_PROBE_FAIL_CONTACT -#define ALARM_HOMING_FAIL_RESET EXEC_ALARM_HOMING_FAIL_RESET -#define ALARM_HOMING_FAIL_DOOR EXEC_ALARM_HOMING_FAIL_DOOR -#define ALARM_HOMING_FAIL_PULLOFF EXEC_ALARM_HOMING_FAIL_PULLOFF -#define ALARM_HOMING_FAIL_APPROACH EXEC_ALARM_HOMING_FAIL_APPROACH +#define ALARM_HARD_LIMIT_ERROR EXEC_ALARM_HARD_LIMIT +#define ALARM_SOFT_LIMIT_ERROR EXEC_ALARM_SOFT_LIMIT +#define ALARM_ABORT_CYCLE EXEC_ALARM_ABORT_CYCLE +#define ALARM_PROBE_FAIL_INITIAL EXEC_ALARM_PROBE_FAIL_INITIAL +#define ALARM_PROBE_FAIL_CONTACT EXEC_ALARM_PROBE_FAIL_CONTACT +#define ALARM_HOMING_FAIL_RESET EXEC_ALARM_HOMING_FAIL_RESET +#define ALARM_HOMING_FAIL_DOOR EXEC_ALARM_HOMING_FAIL_DOOR +#define ALARM_HOMING_FAIL_PULLOFF EXEC_ALARM_HOMING_FAIL_PULLOFF +#define ALARM_HOMING_FAIL_APPROACH EXEC_ALARM_HOMING_FAIL_APPROACH // Define Grbl feedback message codes. Valid values (0-255). #define MESSAGE_CRITICAL_EVENT 1 @@ -111,22 +111,22 @@ const char* errorString(err_t errorNumber); #define MESSAGE_RESTORE_DEFAULTS 9 #define MESSAGE_SPINDLE_RESTORE 10 #define MESSAGE_SLEEP_MODE 11 -#define MESSAGE_SD_FILE_QUIT 60 // mc_reset was called during an SD job +#define MESSAGE_SD_FILE_QUIT 60 // mc_reset was called during an SD job -#define CLIENT_SERIAL 0 -#define CLIENT_BT 1 -#define CLIENT_WEBUI 2 -#define CLIENT_TELNET 3 -#define CLIENT_INPUT 4 -#define CLIENT_ALL 0xFF -#define CLIENT_COUNT 5 // total number of client types regardless if they are used +#define CLIENT_SERIAL 0 +#define CLIENT_BT 1 +#define CLIENT_WEBUI 2 +#define CLIENT_TELNET 3 +#define CLIENT_INPUT 4 +#define CLIENT_ALL 0xFF +#define CLIENT_COUNT 5 // total number of client types regardless if they are used -#define MSG_LEVEL_NONE 0 // set GRBL_MSG_LEVEL in config.h to the level you want to see -#define MSG_LEVEL_ERROR 1 -#define MSG_LEVEL_WARNING 2 -#define MSG_LEVEL_INFO 3 -#define MSG_LEVEL_DEBUG 4 -#define MSG_LEVEL_VERBOSE 5 +#define MSG_LEVEL_NONE 0 // set GRBL_MSG_LEVEL in config.h to the level you want to see +#define MSG_LEVEL_ERROR 1 +#define MSG_LEVEL_WARNING 2 +#define MSG_LEVEL_INFO 3 +#define MSG_LEVEL_DEBUG 4 +#define MSG_LEVEL_VERBOSE 5 // functions to send data to the user. void grbl_send(uint8_t client, const char* text); @@ -181,12 +181,12 @@ void report_build_info(char* line, uint8_t client); void report_gcode_comment(char* comment); #ifdef DEBUG - void report_realtime_debug(); +void report_realtime_debug(); #endif void report_machine_type(uint8_t client); -void report_hex_msg(char* buf, const char *prefix, int len); -void report_hex_msg(uint8_t* buf, const char *prefix, int len); +void report_hex_msg(char* buf, const char* prefix, int len); +void report_hex_msg(uint8_t* buf, const char* prefix, int len); char report_get_axis_letter(uint8_t axis); diff --git a/Grbl_Esp32/serial.cpp b/Grbl_Esp32/serial.cpp index c3216295..944e6f98 100644 --- a/Grbl_Esp32/serial.cpp +++ b/Grbl_Esp32/serial.cpp @@ -72,55 +72,54 @@ void serial_init() { Serial.begin(BAUD_RATE); // reset all buffers serial_reset_read_buffer(CLIENT_ALL); - grbl_send(CLIENT_SERIAL, "\r\n"); // create some white space after ESP32 boot info + grbl_send(CLIENT_SERIAL, "\r\n"); // create some white space after ESP32 boot info serialCheckTaskHandle = 0; // create a task to check for incoming data - xTaskCreatePinnedToCore(serialCheckTask, // task - "serialCheckTask", // name for task - 8192, // size of task stack - NULL, // parameters - 1, // priority + xTaskCreatePinnedToCore(serialCheckTask, // task + "serialCheckTask", // name for task + 8192, // size of task stack + NULL, // parameters + 1, // priority &serialCheckTaskHandle, - 1 // core - ); + 1 // core + ); } - // this task runs and checks for data on all interfaces // REaltime stuff is acted upon, then characters are added to the appropriate buffer void serialCheckTask(void* pvParameters) { - uint8_t data = 0; - uint8_t client = CLIENT_ALL; // who sent the data - while (true) { // run continuously + uint8_t data = 0; + uint8_t client = CLIENT_ALL; // who sent the data + while (true) { // run continuously while (any_client_has_data()) { if (Serial.available()) { client = CLIENT_SERIAL; - data = Serial.read(); + data = Serial.read(); } else if (inputBuffer.available()) { client = CLIENT_INPUT; - data = inputBuffer.read(); + data = inputBuffer.read(); } else { //currently is wifi or BT but better to prepare both can be live #ifdef ENABLE_BLUETOOTH if (SerialBT.hasClient() && SerialBT.available()) { client = CLIENT_BT; - data = SerialBT.read(); + data = SerialBT.read(); //Serial.write(data); // echo all data to serial } else { #endif -#if defined (ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN) +#if defined(ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN) if (Serial2Socket.available()) { client = CLIENT_WEBUI; - data = Serial2Socket.read(); + data = Serial2Socket.read(); } else { #endif -#if defined (ENABLE_WIFI) && defined(ENABLE_TELNET) +#if defined(ENABLE_WIFI) && defined(ENABLE_TELNET) if (telnet_server.available()) { client = CLIENT_TELNET; - data = telnet_server.read(); + data = telnet_server.read(); } #endif -#if defined (ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN) +#if defined(ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN) } #endif #ifdef ENABLE_BLUETOOTH @@ -144,11 +143,11 @@ void serialCheckTask(void* pvParameters) { #ifdef ENABLE_BLUETOOTH bt_config.handle(); #endif -#if defined (ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN) +#if defined(ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN) Serial2Socket.handle_flush(); #endif vTaskDelay(1 / portTICK_RATE_MS); // Yield to other tasks - } // while(true) + } // while(true) } void serial_reset_read_buffer(uint8_t client) { @@ -183,13 +182,13 @@ bool any_client_has_data() { #ifdef ENABLE_BLUETOOTH || (SerialBT.hasClient() && SerialBT.available()) #endif -#if defined (ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN) +#if defined(ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN) || Serial2Socket.available() #endif -#if defined (ENABLE_WIFI) && defined(ENABLE_TELNET) +#if defined(ENABLE_WIFI) && defined(ENABLE_TELNET) || telnet_server.available() #endif - ); + ); } // checks to see if a character is a realtime character @@ -200,48 +199,50 @@ bool is_realtime_command(uint8_t data) { // Act upon a realtime character void execute_realtime_command(uint8_t command, uint8_t client) { switch (command) { - case CMD_RESET: - mc_reset(); // Call motion control reset routine. - break; - case CMD_STATUS_REPORT: - report_realtime_status(client); // direct call instead of setting flag - break; - case CMD_CYCLE_START: - system_set_exec_state_flag(EXEC_CYCLE_START); // Set as true - break; - case CMD_FEED_HOLD: - system_set_exec_state_flag(EXEC_FEED_HOLD); // Set as true - break; - case CMD_SAFETY_DOOR: - system_set_exec_state_flag(EXEC_SAFETY_DOOR); - break; // Set as true - case CMD_JOG_CANCEL: - if (sys.state & STATE_JOG) // Block all other states from invoking motion cancel. - system_set_exec_state_flag(EXEC_MOTION_CANCEL); - break; + case CMD_RESET: + mc_reset(); // Call motion control reset routine. + break; + case CMD_STATUS_REPORT: + report_realtime_status(client); // direct call instead of setting flag + break; + case CMD_CYCLE_START: + system_set_exec_state_flag(EXEC_CYCLE_START); // Set as true + break; + case CMD_FEED_HOLD: + system_set_exec_state_flag(EXEC_FEED_HOLD); // Set as true + break; + case CMD_SAFETY_DOOR: system_set_exec_state_flag(EXEC_SAFETY_DOOR); break; // Set as true + case CMD_JOG_CANCEL: + if (sys.state & STATE_JOG) // Block all other states from invoking motion cancel. + system_set_exec_state_flag(EXEC_MOTION_CANCEL); + break; #ifdef DEBUG - case CMD_DEBUG_REPORT: {uint8_t sreg = SREG; cli(); bit_true(sys_rt_exec_debug, EXEC_DEBUG_REPORT); SREG = sreg;} break; + case CMD_DEBUG_REPORT: { + uint8_t sreg = SREG; + cli(); + bit_true(sys_rt_exec_debug, EXEC_DEBUG_REPORT); + SREG = sreg; + } break; #endif - case CMD_FEED_OVR_RESET: system_set_exec_motion_override_flag(EXEC_FEED_OVR_RESET); break; - case CMD_FEED_OVR_COARSE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_PLUS); break; - case CMD_FEED_OVR_COARSE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_MINUS); break; - case CMD_FEED_OVR_FINE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_PLUS); break; - case CMD_FEED_OVR_FINE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_MINUS); break; - case CMD_RAPID_OVR_RESET: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_RESET); break; - case CMD_RAPID_OVR_MEDIUM: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_MEDIUM); break; - case CMD_RAPID_OVR_LOW: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_LOW); break; - case CMD_SPINDLE_OVR_RESET: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_RESET); break; - case CMD_SPINDLE_OVR_COARSE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_PLUS); break; - case CMD_SPINDLE_OVR_COARSE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_MINUS); break; - case CMD_SPINDLE_OVR_FINE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_PLUS); break; - case CMD_SPINDLE_OVR_FINE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_MINUS); break; - case CMD_SPINDLE_OVR_STOP: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP); break; + case CMD_FEED_OVR_RESET: system_set_exec_motion_override_flag(EXEC_FEED_OVR_RESET); break; + case CMD_FEED_OVR_COARSE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_PLUS); break; + case CMD_FEED_OVR_COARSE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_MINUS); break; + case CMD_FEED_OVR_FINE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_PLUS); break; + case CMD_FEED_OVR_FINE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_MINUS); break; + case CMD_RAPID_OVR_RESET: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_RESET); break; + case CMD_RAPID_OVR_MEDIUM: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_MEDIUM); break; + case CMD_RAPID_OVR_LOW: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_LOW); break; + case CMD_SPINDLE_OVR_RESET: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_RESET); break; + case CMD_SPINDLE_OVR_COARSE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_PLUS); break; + case CMD_SPINDLE_OVR_COARSE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_MINUS); break; + case CMD_SPINDLE_OVR_FINE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_PLUS); break; + case CMD_SPINDLE_OVR_FINE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_MINUS); break; + case CMD_SPINDLE_OVR_STOP: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP); break; #ifdef COOLANT_FLOOD_PIN - case CMD_COOLANT_FLOOD_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_FLOOD_OVR_TOGGLE); break; + case CMD_COOLANT_FLOOD_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_FLOOD_OVR_TOGGLE); break; #endif #ifdef COOLANT_MIST_PIN - case CMD_COOLANT_MIST_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_MIST_OVR_TOGGLE); break; + case CMD_COOLANT_MIST_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_MIST_OVR_TOGGLE); break; #endif } } - diff --git a/Grbl_Esp32/serial.h b/Grbl_Esp32/serial.h index 06750764..c31c621c 100644 --- a/Grbl_Esp32/serial.h +++ b/Grbl_Esp32/serial.h @@ -23,14 +23,14 @@ #include "grbl.h" #ifndef RX_BUFFER_SIZE - #define RX_BUFFER_SIZE 128 +# define RX_BUFFER_SIZE 128 #endif #ifndef TX_BUFFER_SIZE - #ifdef USE_LINE_NUMBERS - #define TX_BUFFER_SIZE 112 - #else - #define TX_BUFFER_SIZE 104 - #endif +# ifdef USE_LINE_NUMBERS +# define TX_BUFFER_SIZE 112 +# else +# define TX_BUFFER_SIZE 104 +# endif #endif #define SERIAL_NO_DATA 0xff diff --git a/Grbl_Esp32/serial2socket.cpp b/Grbl_Esp32/serial2socket.cpp index 20ffef24..d8500268 100644 --- a/Grbl_Esp32/serial2socket.cpp +++ b/Grbl_Esp32/serial2socket.cpp @@ -18,43 +18,39 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifdef ARDUINO_ARCH_ESP32 - #include "grbl.h" -#if defined (ENABLE_WIFI) && defined(ENABLE_HTTP) +#if defined(ENABLE_WIFI) && defined(ENABLE_HTTP) - -#include "serial2socket.h" -#include "web_server.h" -#include -#include +# include "serial2socket.h" +# include "web_server.h" +# include +# include Serial_2_Socket Serial2Socket; - Serial_2_Socket::Serial_2_Socket() { - _web_socket = NULL; + _web_socket = NULL; _TXbufferSize = 0; _RXbufferSize = 0; - _RXbufferpos = 0; + _RXbufferpos = 0; } Serial_2_Socket::~Serial_2_Socket() { - if (_web_socket) detachWS(); + if (_web_socket) + detachWS(); _TXbufferSize = 0; _RXbufferSize = 0; - _RXbufferpos = 0; + _RXbufferpos = 0; } void Serial_2_Socket::begin(long speed) { _TXbufferSize = 0; _RXbufferSize = 0; - _RXbufferpos = 0; + _RXbufferpos = 0; } void Serial_2_Socket::end() { _TXbufferSize = 0; _RXbufferSize = 0; - _RXbufferpos = 0; + _RXbufferpos = 0; } long Serial_2_Socket::baudRate() { @@ -63,7 +59,7 @@ long Serial_2_Socket::baudRate() { bool Serial_2_Socket::attachWS(void* web_socket) { if (web_socket) { - _web_socket = web_socket; + _web_socket = web_socket; _TXbufferSize = 0; return true; } @@ -82,9 +78,9 @@ int Serial_2_Socket::available() { return _RXbufferSize; } - size_t Serial_2_Socket::write(uint8_t c) { - if (!_web_socket) return 0; + if (!_web_socket) + return 0; write(&c, 1); return 1; } @@ -97,10 +93,12 @@ size_t Serial_2_Socket::write(const uint8_t* buffer, size_t size) { log_i("[SOCKET]No socket"); return 0; } -#if defined(ENABLE_SERIAL2SOCKET_OUT) - if (_TXbufferSize == 0)_lastflush = millis(); +# if defined(ENABLE_SERIAL2SOCKET_OUT) + if (_TXbufferSize == 0) + _lastflush = millis(); //send full line - if (_TXbufferSize + size > TXBUFFERSIZE) flush(); + if (_TXbufferSize + size > TXBUFFERSIZE) + flush(); //need periodic check to force to flush in case of no end for (int i = 0; i < size; i++) { _TXbuffer[_TXbufferSize] = buffer[i]; @@ -108,43 +106,49 @@ size_t Serial_2_Socket::write(const uint8_t* buffer, size_t size) { } log_i("[SOCKET]buffer size %d", _TXbufferSize); handle_flush(); -#endif +# endif return size; } int Serial_2_Socket::peek(void) { - if (_RXbufferSize > 0)return _RXbuffer[_RXbufferpos]; - else return -1; + if (_RXbufferSize > 0) + return _RXbuffer[_RXbufferpos]; + else + return -1; } bool Serial_2_Socket::push(const char* data) { -#if defined(ENABLE_SERIAL2SOCKET_IN) +# if defined(ENABLE_SERIAL2SOCKET_IN) int data_size = strlen(data); if ((data_size + _RXbufferSize) <= RXBUFFERSIZE) { int current = _RXbufferpos + _RXbufferSize; - if (current > RXBUFFERSIZE) current = current - RXBUFFERSIZE; + if (current > RXBUFFERSIZE) + current = current - RXBUFFERSIZE; for (int i = 0; i < data_size; i++) { - if (current > (RXBUFFERSIZE - 1)) current = 0; + if (current > (RXBUFFERSIZE - 1)) + current = 0; _RXbuffer[current] = data[i]; - current ++; + current++; } _RXbufferSize += strlen(data); return true; } return false; -#else +# else return true; -#endif +# endif } int Serial_2_Socket::read(void) { if (_RXbufferSize > 0) { int v = _RXbuffer[_RXbufferpos]; _RXbufferpos++; - if (_RXbufferpos > (RXBUFFERSIZE - 1))_RXbufferpos = 0; + if (_RXbufferpos > (RXBUFFERSIZE - 1)) + _RXbufferpos = 0; _RXbufferSize--; return v; - } else return -1; + } else + return -1; } void Serial_2_Socket::handle_flush() { @@ -170,6 +174,4 @@ void Serial_2_Socket::flush(void) { } } -#endif // ENABLE_WIFI - -#endif // ARDUINO_ARCH_ESP32 +#endif // ENABLE_WIFI diff --git a/Grbl_Esp32/serial2socket.h b/Grbl_Esp32/serial2socket.h index 82d6d2f6..d0d9d23d 100644 --- a/Grbl_Esp32/serial2socket.h +++ b/Grbl_Esp32/serial2socket.h @@ -20,54 +20,43 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #include "Print.h" #define TXBUFFERSIZE 1200 #define RXBUFFERSIZE 128 #define FLUSHTIMEOUT 500 -class Serial_2_Socket: public Print { - public: +class Serial_2_Socket : public Print { +public: Serial_2_Socket(); ~Serial_2_Socket(); size_t write(uint8_t c); size_t write(const uint8_t* buffer, size_t size); - inline size_t write(const char* s) { - return write((uint8_t*) s, strlen(s)); - } - inline size_t write(unsigned long n) { - return write((uint8_t) n); - } - inline size_t write(long n) { - return write((uint8_t) n); - } - inline size_t write(unsigned int n) { - return write((uint8_t) n); - } - inline size_t write(int n) { - return write((uint8_t) n); - } - long baudRate(); - void begin(long speed); - void end(); - int available(); - int peek(void); - int read(void); - bool push(const char* data); - void flush(void); - void handle_flush(); - operator bool() const; - bool attachWS(void* web_socket); - bool detachWS(); - private: + inline size_t write(const char* s) { return write((uint8_t*)s, strlen(s)); } + inline size_t write(unsigned long n) { return write((uint8_t)n); } + inline size_t write(long n) { return write((uint8_t)n); } + inline size_t write(unsigned int n) { return write((uint8_t)n); } + inline size_t write(int n) { return write((uint8_t)n); } + long baudRate(); + void begin(long speed); + void end(); + int available(); + int peek(void); + int read(void); + bool push(const char* data); + void flush(void); + void handle_flush(); + operator bool() const; + bool attachWS(void* web_socket); + bool detachWS(); + +private: uint32_t _lastflush; - void* _web_socket; - uint8_t _TXbuffer[TXBUFFERSIZE]; + void* _web_socket; + uint8_t _TXbuffer[TXBUFFERSIZE]; uint16_t _TXbufferSize; - uint8_t _RXbuffer[RXBUFFERSIZE]; + uint8_t _RXbuffer[RXBUFFERSIZE]; uint16_t _RXbufferSize; uint16_t _RXbufferpos; }; - extern Serial_2_Socket Serial2Socket; diff --git a/Grbl_Esp32/servo_axis.cpp b/Grbl_Esp32/servo_axis.cpp index 9d06b86a..fec865c4 100644 --- a/Grbl_Esp32/servo_axis.cpp +++ b/Grbl_Esp32/servo_axis.cpp @@ -28,201 +28,200 @@ static TaskHandle_t servosSyncTaskHandle = 0; -#ifdef SERVO_X_PIN - ServoAxis X_Servo_Axis(X_AXIS, SERVO_X_PIN); -#endif -#ifdef SERVO_Y_PIN - ServoAxis Y_Servo_Axis(Y_AXIS, SERVO_Y_PIN); -#endif -#ifdef SERVO_Z_PIN - ServoAxis Z_Servo_Axis(Z_AXIS, SERVO_Z_PIN); -#endif +# ifdef SERVO_X_PIN +ServoAxis X_Servo_Axis(X_AXIS, SERVO_X_PIN); +# endif +# ifdef SERVO_Y_PIN +ServoAxis Y_Servo_Axis(Y_AXIS, SERVO_Y_PIN); +# endif +# ifdef SERVO_Z_PIN +ServoAxis Z_Servo_Axis(Z_AXIS, SERVO_Z_PIN); +# endif -#ifdef SERVO_A_PIN - ServoAxis A_Servo_Axis(A_AXIS, SERVO_A_PIN); -#endif -#ifdef SERVO_B_PIN - ServoAxis B_Servo_Axis(B_AXIS, SERVO_B_PIN); -#endif -#ifdef SERVO_C_PIN - ServoAxis C_Servo_Axis(C_AXIS, SERVO_C_PIN); -#endif +# ifdef SERVO_A_PIN +ServoAxis A_Servo_Axis(A_AXIS, SERVO_A_PIN); +# endif +# ifdef SERVO_B_PIN +ServoAxis B_Servo_Axis(B_AXIS, SERVO_B_PIN); +# endif +# ifdef SERVO_C_PIN +ServoAxis C_Servo_Axis(C_AXIS, SERVO_C_PIN); +# endif void init_servos() { // ======================== X Axis =========================== -#ifdef SERVO_X_PIN +# ifdef SERVO_X_PIN grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "X Servo range %4.3f to %4.3f", SERVO_X_RANGE_MIN, SERVO_X_RANGE_MAX); X_Servo_Axis.init(); X_Servo_Axis.set_range(SERVO_X_RANGE_MIN, SERVO_X_RANGE_MAX); -#ifdef SERVO_X_HOMING_TYPE +# ifdef SERVO_X_HOMING_TYPE X_Servo_Axis.set_homing_type(SERVO_X_HOMING_TYPE); -#endif -#ifdef SERVO_X_HOME_POS +# endif +# ifdef SERVO_X_HOME_POS X_Servo_Axis.set_homing_position(SERVO_X_HOME_POS); -#endif -#ifdef SERVO_X_MPOS // value should be true or false +# endif +# ifdef SERVO_X_MPOS // value should be true or false X_Servo_Axis.set_use_mpos(SERVO_X_MPOS); -#endif -#ifdef SERVO_X_DISABLE_ON_ALARM +# endif +# ifdef SERVO_X_DISABLE_ON_ALARM set_disable_on_alarm(SERVO_X_DISABLE_ON_ALARM); -#endif -#ifdef SERVO_X_DISABLE_WITH_STEPPERS +# endif +# ifdef SERVO_X_DISABLE_WITH_STEPPERS set_disable_with_steppers(SERVO_X_DISABLE_WITH_STEPPERS); -#endif -#endif +# endif +# endif // ======================== Y Axis =========================== -#ifdef SERVO_Y_PIN +# ifdef SERVO_Y_PIN grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Y Servo range %4.3f to %4.3f", SERVO_Y_RANGE_MIN, SERVO_Y_RANGE_MAX); Y_Servo_Axis.init(); Y_Servo_Axis.set_range(SERVO_Y_RANGE_MIN, SERVO_Y_RANGE_MAX); -#ifdef SERVO_Y_HOMING_TYPE +# ifdef SERVO_Y_HOMING_TYPE Y_Servo_Axis.set_homing_type(SERVO_Y_HOMING_TYPE); -#endif -#ifdef SERVO_Y_HOME_POS +# endif +# ifdef SERVO_Y_HOME_POS Y_Servo_Axis.set_homing_position(SERVO_Y_HOME_POS); -#endif -#ifdef SERVO_Y_MPOS // value should be true or false +# endif +# ifdef SERVO_Y_MPOS // value should be true or false Y_Servo_Axis.set_use_mpos(SERVO_Y_MPOS); -#endif -#ifdef SERVO_Y_DISABLE_ON_ALARM +# endif +# ifdef SERVO_Y_DISABLE_ON_ALARM set_disable_on_alarm(SERVO_Y_DISABLE_ON_ALARM); -#endif -#ifdef SERVO_Y_DISABLE_WITH_STEPPERS +# endif +# ifdef SERVO_Y_DISABLE_WITH_STEPPERS set_disable_with_steppers(SERVO_Y_DISABLE_WITH_STEPPERS); -#endif -#endif +# endif +# endif // ======================== Z Axis =========================== -#ifdef SERVO_Z_PIN +# ifdef SERVO_Z_PIN grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Z Servo range %4.3f to %4.3f", SERVO_Z_RANGE_MIN, SERVO_Z_RANGE_MAX); Z_Servo_Axis.init(); Z_Servo_Axis.set_range(SERVO_Z_RANGE_MIN, SERVO_Z_RANGE_MAX); -#ifdef SERVO_Z_HOMING_TYPE +# ifdef SERVO_Z_HOMING_TYPE Z_Servo_Axis.set_homing_type(SERVO_Z_HOMING_TYPE); -#endif -#ifdef SERVO_Z_HOME_POS +# endif +# ifdef SERVO_Z_HOME_POS Z_Servo_Axis.set_homing_position(SERVO_Z_HOME_POS); -#endif -#ifdef SERVO_Z_MPOS // value should be true or false +# endif +# ifdef SERVO_Z_MPOS // value should be true or false Z_Servo_Axis.set_use_mpos(SERVO_Z_MPOS); -#endif -#ifdef SERVO_Z_DISABLE_ON_ALARM +# endif +# ifdef SERVO_Z_DISABLE_ON_ALARM set_disable_on_alarm(SERVO_Z_DISABLE_ON_ALARM); -#endif -#ifdef SERVO_Z_DISABLE_WITH_STEPPERS +# endif +# ifdef SERVO_Z_DISABLE_WITH_STEPPERS set_disable_with_steppers(SERVO_Z_DISABLE_WITH_STEPPERS); -#endif -#endif +# endif +# endif // ======================== A Axis =========================== -#ifdef SERVO_A_PIN +# ifdef SERVO_A_PIN grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "A Servo range %4.3f to %4.3f", SERVO_A_RANGE_MIN, SERVO_A_RANGE_MAX); A_Servo_Axis.init(); A_Servo_Axis.set_range(SERVO_A_RANGE_MIN, SERVO_A_RANGE_MAX); -#ifdef SERVO_A_HOMING_TYPE +# ifdef SERVO_A_HOMING_TYPE A_Servo_Axis.set_homing_type(SERVO_A_HOMING_TYPE); -#endif -#ifdef SERVO_A_HOME_POS +# endif +# ifdef SERVO_A_HOME_POS A_Servo_Axis.set_homing_position(SERVO_A_HOME_POS); -#endif -#ifdef SERVO_A_MPOS // value should be true or false +# endif +# ifdef SERVO_A_MPOS // value should be true or false A_Servo_Axis.set_use_mpos(SERVO_A_MPOS); -#endif -#ifdef SERVO_A_DISABLE_ON_ALARM +# endif +# ifdef SERVO_A_DISABLE_ON_ALARM set_disable_on_alarm(SERVO_A_DISABLE_ON_ALARM); -#endif -#ifdef SERVO_A_DISABLE_WITH_STEPPERS +# endif +# ifdef SERVO_A_DISABLE_WITH_STEPPERS set_disable_with_steppers(SERVO_A_DISABLE_WITH_STEPPERS); -#endif -#endif +# endif +# endif // ======================== B Axis =========================== -#ifdef SERVO_B_PIN +# ifdef SERVO_B_PIN grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "B Servo range %4.3f to %4.3f", SERVO_B_RANGE_MIN, SERVO_B_RANGE_MAX); B_Servo_Axis.init(); B_Servo_Axis.set_range(SERVO_B_RANGE_MIN, SERVO_B_RANGE_MAX); -#ifdef SERVO_B_HOMING_TYPE +# ifdef SERVO_B_HOMING_TYPE B_Servo_Axis.set_homing_type(SERVO_B_HOMING_TYPE); -#endif -#ifdef SERVO_B_HOME_POS +# endif +# ifdef SERVO_B_HOME_POS B_Servo_Axis.set_homing_position(SERVO_B_HOME_POS); -#endif -#ifdef SERVO_B_MPOS // value should be true or false +# endif +# ifdef SERVO_B_MPOS // value should be true or false B_Servo_Axis.set_use_mpos(SERVO_B_MPOS); -#endif -#ifdef SERVO_B_DISABLE_ON_ALARM +# endif +# ifdef SERVO_B_DISABLE_ON_ALARM set_disable_on_alarm(SERVO_B_DISABLE_ON_ALARM); -#endif -#ifdef SERVO_B_DISABLE_WITH_STEPPERS +# endif +# ifdef SERVO_B_DISABLE_WITH_STEPPERS set_disable_with_steppers(SERVO_B_DISABLE_WITH_STEPPERS); -#endif -#endif +# endif +# endif // ======================== C Axis =========================== -#ifdef SERVO_C_PIN +# ifdef SERVO_C_PIN grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "C Servo range %4.3f to %4.3f", SERVO_C_RANGE_MIN, SERVO_C_RANGE_MAX); C_Servo_Axis.init(); C_Servo_Axis.set_range(SERVO_C_RANGE_MIN, SERVO_C_RANGE_MAX); -#ifdef SERVO_C_HOMING_TYPE +# ifdef SERVO_C_HOMING_TYPE C_Servo_Axis.set_homing_type(SERVO_C_HOMING_TYPE); -#endif -#ifdef SERVO_C_HOME_POS +# endif +# ifdef SERVO_C_HOME_POS C_Servo_Axis.set_homing_position(SERVO_C_HOME_POS); -#endif -#ifdef SERVO_C_MPOS // value should be true or false +# endif +# ifdef SERVO_C_MPOS // value should be true or false C_Servo_Axis.set_use_mpos(SERVO_C_MPOS); -#endif -#ifdef SERVO_C_DISABLE_ON_ALARM +# endif +# ifdef SERVO_C_DISABLE_ON_ALARM set_disable_on_alarm(SERVO_C_DISABLE_ON_ALARM); -#endif -#ifdef SERVO_C_DISABLE_WITH_STEPPERS +# endif +# ifdef SERVO_C_DISABLE_WITH_STEPPERS set_disable_with_steppers(SERVO_C_DISABLE_WITH_STEPPERS); -#endif -#endif +# endif +# endif // setup a task that will calculate the determine and set the servo positions - xTaskCreatePinnedToCore(servosSyncTask, // task - "servosSyncTask", // name for task - 4096, // size of task stack - NULL, // parameters - 1, // priority + xTaskCreatePinnedToCore(servosSyncTask, // task + "servosSyncTask", // name for task + 4096, // size of task stack + NULL, // parameters + 1, // priority &servosSyncTaskHandle, - 0 // core - ); + 0 // core + ); } - // this is the task void servosSyncTask(void* pvParameters) { - TickType_t xLastWakeTime; + TickType_t xLastWakeTime; const TickType_t xServoFrequency = SERVO_TIMER_INT_FREQ; // in ticks (typically ms) - xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time. - while (true) { // don't ever return from this or the task dies -#ifdef SERVO_X_PIN + xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time. + while (true) { // don't ever return from this or the task dies +# ifdef SERVO_X_PIN X_Servo_Axis.set_location(); -#endif -#ifdef SERVO_Y_PIN +# endif +# ifdef SERVO_Y_PIN Y_Servo_Axis.set_location(); -#endif -#ifdef SERVO_Z_PIN +# endif +# ifdef SERVO_Z_PIN Z_Servo_Axis.set_location(); -#endif -#ifdef SERVO_A_PIN +# endif +# ifdef SERVO_A_PIN A_Servo_Axis.set_location(); -#endif -#ifdef SERVO_B_PIN +# endif +# ifdef SERVO_B_PIN B_Servo_Axis.set_location(); -#endif -#ifdef SERVO_C_PIN +# endif +# ifdef SERVO_C_PIN C_Servo_Axis.set_location(); -#endif +# endif vTaskDelayUntil(&xLastWakeTime, xServoFrequency); } } // =============================== Class Stuff ================================= // -ServoAxis::ServoAxis(uint8_t axis, uint8_t pin_num) { // constructor - _axis = axis; - _pin_num = pin_num; +ServoAxis::ServoAxis(uint8_t axis, uint8_t pin_num) { // constructor + _axis = axis; + _pin_num = pin_num; _channel_num = sys_get_next_PWM_chan_num(); - _showError = true; // this will be used to show calibration error only once - _use_mpos = true; // default is to use the machine position rather than work position + _showError = true; // this will be used to show calibration error only once + _use_mpos = true; // default is to use the machine position rather than work position } void ServoAxis::init() { @@ -235,10 +234,10 @@ void ServoAxis::init() { void ServoAxis::set_location() { // These are the pulse lengths for the minimum and maximum positions // Note: Some machines will have the physical max/min inverted with pulse length max/min due to invert setting $3=... - float servo_pulse_min, servo_pulse_max; - float min_pulse_cal, max_pulse_cal; // calibration values in percent 110% = 1.1 + float servo_pulse_min, servo_pulse_max; + float min_pulse_cal, max_pulse_cal; // calibration values in percent 110% = 1.1 uint32_t servo_pulse_len; - float servo_pos, mpos, offset; + float servo_pos, mpos, offset; // skip location if we are in alarm mode if (_disable_on_alarm && (sys.state == STATE_ALARM)) { disable(); @@ -250,14 +249,14 @@ void ServoAxis::set_location() { return; } if ((_homing_type == SERVO_HOMING_TARGET) && (sys.state == STATE_HOMING)) { - servo_pos = _homing_position; // go to servos home position + servo_pos = _homing_position; // go to servos home position } else { mpos = system_convert_axis_steps_to_mpos(sys_position, _axis); // get the axis machine position in mm if (_use_mpos) servo_pos = mpos; else { - offset = gc_state.coord_system[_axis] + gc_state.coord_offset[_axis]; // get the current axis work offset - servo_pos = mpos - offset; // determine the current work position + offset = gc_state.coord_system[_axis] + gc_state.coord_offset[_axis]; // get the current axis work offset + servo_pos = mpos - offset; // determine the current work position } } // 1. Get the pulse ranges of the servos @@ -270,17 +269,17 @@ void ServoAxis::set_location() { if (bit_istrue(dir_invert_mask->get(), bit(_axis))) // this allows the user to change the direction via settings swap(servo_pulse_min, servo_pulse_max); // get the calibration values - if (_cal_is_valid()) { // if calibration settings are OK then apply them + if (_cal_is_valid()) { // if calibration settings are OK then apply them // apply a calibration // the cals apply differently if the direction is reverse (i.e. longer pulse is lower position) - if (bit_isfalse(dir_invert_mask->get(), bit(_axis))) { // normal direction + if (bit_isfalse(dir_invert_mask->get(), bit(_axis))) { // normal direction min_pulse_cal = 2.0 - (axis_settings[_axis]->steps_per_mm->get() / 100.0); max_pulse_cal = (axis_settings[_axis]->max_travel->get() / 100.0); - } else { // inverted direction + } else { // inverted direction min_pulse_cal = (axis_settings[_axis]->steps_per_mm->get() / 100.0); max_pulse_cal = 2.0 - (axis_settings[_axis]->max_travel->get() / -100.0); } - } else { // settings are not valid so don't apply any calibration + } else { // settings are not valid so don't apply any calibration min_pulse_cal = 1.0; max_pulse_cal = 1.0; } @@ -293,7 +292,7 @@ void ServoAxis::set_location() { } void ServoAxis::_write_pwm(uint32_t duty) { - if (ledcRead(_channel_num) != duty) // only write if it is changing + if (ledcRead(_channel_num) != duty) // only write if it is changing ledcWrite(_channel_num, duty); } @@ -319,7 +318,7 @@ bool ServoAxis::_cal_is_valid() { if ((travel < -SERVO_CAL_MAX) || travel > -SERVO_CAL_MIN) { if (_showError) { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo calibration ($13%d) value error. Reset to 100", _axis); - char reset_val[] = "-100"; // stored as a negative + char reset_val[] = "-100"; // stored as a negative axis_settings[_axis]->max_travel->setStringValue(reset_val); } settingsOK = false; @@ -378,6 +377,4 @@ void ServoAxis::set_use_mpos(bool use_mpos) { _use_mpos = use_mpos; } - - #endif diff --git a/Grbl_Esp32/servo_axis.h b/Grbl_Esp32/servo_axis.h index ddd13a94..fe9399ac 100644 --- a/Grbl_Esp32/servo_axis.h +++ b/Grbl_Esp32/servo_axis.h @@ -55,21 +55,20 @@ #include "Motors/RcServoClass.h" -#define SERVO_HOMING_OFF 0 // servo is off during homing -#define SERVO_HOMING_TARGET 1 // servo is send to a location during homing +#define SERVO_HOMING_OFF 0 // servo is off during homing +#define SERVO_HOMING_TARGET 1 // servo is send to a location during homing extern float my_location; void init_servos(); void servosSyncTask(void* pvParameters); - class ServoAxis { - public: - ServoAxis(uint8_t axis, uint8_t pin_num); // constructor +public: + ServoAxis(uint8_t axis, uint8_t pin_num); // constructor void init(); void set_location(); - void disable(); // sets PWM to 0% duty cycle. Most servos can be manually moved in this state + void disable(); // sets PWM to 0% duty cycle. Most servos can be manually moved in this state void set_range(float min, float max); void set_homing_type(uint8_t homing_type); void set_homing_position(float homing_position); @@ -77,28 +76,26 @@ class ServoAxis { void set_disable_with_steppers(bool disable_with_steppers); void set_use_mpos(bool use_mpos); - private: - int _axis; // these should be assign in constructor using Grbl X_AXIS type values - int _pin_num; // The GPIO pin being used - int _channel_num; // The PWM channel +private: + int _axis; // these should be assign in constructor using Grbl X_AXIS type values + int _pin_num; // The GPIO pin being used + int _channel_num; // The PWM channel bool _showError; - uint32_t _pwm_freq = SERVO_PULSE_FREQ; + uint32_t _pwm_freq = SERVO_PULSE_FREQ; uint32_t _pwm_resolution_bits = SERVO_PULSE_RES_BITS; - float _pulse_min = SERVO_MIN_PULSE; // in pwm counts - float _pulse_max = SERVO_MAX_PULSE; // in pwm counts - float _position_min = SERVO_POSITION_MIN_DEFAULT; // position in millimeters - float _position_max = SERVO_POSITION_MAX_DEFAULT; // position in millimeters + float _pulse_min = SERVO_MIN_PULSE; // in pwm counts + float _pulse_max = SERVO_MAX_PULSE; // in pwm counts + float _position_min = SERVO_POSITION_MIN_DEFAULT; // position in millimeters + float _position_max = SERVO_POSITION_MAX_DEFAULT; // position in millimeters - - uint8_t _homing_type = SERVO_HOMING_OFF; - float _homing_position = SERVO_POSITION_MAX_DEFAULT; - bool _disable_on_alarm = true; - bool _disable_with_steppers = false; - bool _use_mpos = true; + uint8_t _homing_type = SERVO_HOMING_OFF; + float _homing_position = SERVO_POSITION_MAX_DEFAULT; + bool _disable_on_alarm = true; + bool _disable_with_steppers = false; + bool _use_mpos = true; bool _validate_cal_settings(); void _write_pwm(uint32_t duty); - bool _cal_is_valid(); // checks to see if calibration values are in acceptable range - + bool _cal_is_valid(); // checks to see if calibration values are in acceptable range }; diff --git a/Grbl_Esp32/settings.cpp b/Grbl_Esp32/settings.cpp index 94c58333..280decf1 100644 --- a/Grbl_Esp32/settings.cpp +++ b/Grbl_Esp32/settings.cpp @@ -24,11 +24,10 @@ #include "grbl.h" - // Read selected coordinate data from EEPROM. Updates pointed coord_data value. uint8_t settings_read_coord_data(uint8_t coord_select, float* coord_data) { uint32_t addr = coord_select * (sizeof(float) * N_AXIS + 1) + EEPROM_ADDR_PARAMETERS; - if (!(memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float)*N_AXIS))) { + if (!(memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float) * N_AXIS))) { // Reset with default zero vector clear_vector_float(coord_data); settings_write_coord_data(coord_select, coord_data); @@ -43,7 +42,7 @@ void settings_write_coord_data(uint8_t coord_select, float* coord_data) { protocol_buffer_synchronize(); #endif uint32_t addr = coord_select * (sizeof(float) * N_AXIS + 1) + EEPROM_ADDR_PARAMETERS; - memcpy_to_eeprom_with_checksum(addr, (char*)coord_data, sizeof(float)*N_AXIS); + memcpy_to_eeprom_with_checksum(addr, (char*)coord_data, sizeof(float) * N_AXIS); } // Method to store build info into EEPROM @@ -57,7 +56,7 @@ void settings_store_build_info(const char* line) { uint8_t settings_read_build_info(char* line) { if (!(memcpy_from_eeprom_with_checksum((char*)line, EEPROM_ADDR_BUILD_INFO, LINE_BUFFER_SIZE))) { // Reset line with default value - line[0] = 0; // Empty line + line[0] = 0; // Empty line settings_store_build_info(line); return (false); } @@ -74,4 +73,3 @@ uint8_t get_step_pin_mask(uint8_t axis_idx) { uint8_t get_direction_pin_mask(uint8_t axis_idx) { return bit(axis_idx); } - diff --git a/Grbl_Esp32/settings.h b/Grbl_Esp32/settings.h index e941c681..d2e8db25 100644 --- a/Grbl_Esp32/settings.h +++ b/Grbl_Esp32/settings.h @@ -26,38 +26,37 @@ #include "grbl.h" - // Define status reporting boolean enable bit flags in status_report_mask -#define BITFLAG_RT_STATUS_POSITION_TYPE bit(0) -#define BITFLAG_RT_STATUS_BUFFER_STATE bit(1) +#define BITFLAG_RT_STATUS_POSITION_TYPE bit(0) +#define BITFLAG_RT_STATUS_BUFFER_STATE bit(1) // Define settings restore bitflags. #define SETTINGS_RESTORE_DEFAULTS bit(0) #define SETTINGS_RESTORE_PARAMETERS bit(1) #define SETTINGS_RESTORE_STARTUP_LINES bit(2) #define SETTINGS_RESTORE_BUILD_INFO bit(3) -#define SETTINGS_RESTORE_WIFI_SETTINGS bit(4) +#define SETTINGS_RESTORE_WIFI_SETTINGS bit(4) #ifndef SETTINGS_RESTORE_ALL - #define SETTINGS_RESTORE_ALL 0xFF // All bitflags +# define SETTINGS_RESTORE_ALL 0xFF // All bitflags #endif // Define EEPROM memory address location values for Grbl settings and parameters // NOTE: The Atmega328p has 1KB EEPROM. The upper half is reserved for parameters and // the startup script. The lower half contains the global settings and space for future // developments. -#define EEPROM_SIZE 1024U -#define EEPROM_ADDR_PARAMETERS 512U -#define EEPROM_ADDR_BUILD_INFO 942U +#define EEPROM_SIZE 1024U +#define EEPROM_ADDR_PARAMETERS 512U +#define EEPROM_ADDR_BUILD_INFO 942U // Define EEPROM address indexing for coordinate parameters -#define N_COORDINATE_SYSTEM 6 // Number of supported work coordinate systems (from index 1) -#define SETTING_INDEX_NCOORD N_COORDINATE_SYSTEM+1 // Total number of system stored (from index 0) +#define N_COORDINATE_SYSTEM 6 // Number of supported work coordinate systems (from index 1) +#define SETTING_INDEX_NCOORD N_COORDINATE_SYSTEM + 1 // Total number of system stored (from index 0) // NOTE: Work coordinate indices are (0=G54, 1=G55, ... , 6=G59) -#define SETTING_INDEX_G28 N_COORDINATE_SYSTEM // Home position 1 -#define SETTING_INDEX_G30 N_COORDINATE_SYSTEM+1 // Home position 2 +#define SETTING_INDEX_G28 N_COORDINATE_SYSTEM // Home position 1 +#define SETTING_INDEX_G30 N_COORDINATE_SYSTEM + 1 // Home position 2 // #define SETTING_INDEX_G92 N_COORDINATE_SYSTEM+2 // Coordinate offset (G92.2,G92.3 not supported) -#define USER_SETTING_COUNT 5 // for user to define for their machine +#define USER_SETTING_COUNT 5 // for user to define for their machine // Initialize the configuration subsystem (load settings from EEPROM) void settings_init(); @@ -65,7 +64,7 @@ void settings_restore(uint8_t restore_flag); void write_global_settings(); uint8_t settings_read_build_info(char* line); -void settings_store_build_info(const char* line); +void settings_store_build_info(const char* line); // Writes selected coordinate data to EEPROM void settings_write_coord_data(uint8_t coord_select, float* coord_data); diff --git a/Grbl_Esp32/solenoid_pen.cpp b/Grbl_Esp32/solenoid_pen.cpp index 822f6559..1012b9cf 100644 --- a/Grbl_Esp32/solenoid_pen.cpp +++ b/Grbl_Esp32/solenoid_pen.cpp @@ -28,28 +28,28 @@ int8_t solenoid_pwm_chan_num; static TaskHandle_t solenoidSyncTaskHandle = 0; // used to delay turn on -bool solenoid_pen_enable; +bool solenoid_pen_enable; uint16_t solenoide_hold_count; void solenoid_init() { grbl_send(CLIENT_SERIAL, "[MSG:Solenoid Mode]\r\n"); // startup message //validate_servo_settings(true); // display any calibration errors - solenoid_pen_enable = false; // start delay has not completed yet. - solenoide_hold_count = 0; // initialize + solenoid_pen_enable = false; // start delay has not completed yet. + solenoide_hold_count = 0; // initialize // setup PWM channel solenoid_pwm_chan_num = sys_get_next_PWM_chan_num(); ledcSetup(solenoid_pwm_chan_num, SOLENOID_PWM_FREQ, SOLENOID_PWM_RES_BITS); ledcAttachPin(SOLENOID_PEN_PIN, solenoid_pwm_chan_num); - solenoid_disable(); // start it it off + solenoid_disable(); // start it it off // setup a task that will calculate the determine and set the servo position - xTaskCreatePinnedToCore(solenoidSyncTask, // task - "solenoidSyncTask", // name for task - 4096, // size of task stack - NULL, // parameters - 1, // priority + xTaskCreatePinnedToCore(solenoidSyncTask, // task + "solenoidSyncTask", // name for task + 4096, // size of task stack + NULL, // parameters + 1, // priority &solenoidSyncTaskHandle, - 0 // core - ); + 0 // core + ); } // turn off the PWM (0 duty) @@ -59,20 +59,20 @@ void solenoid_disable() { // this is the task void solenoidSyncTask(void* pvParameters) { - int32_t current_position[N_AXIS]; // copy of current location - float m_pos[N_AXIS]; // machine position in mm - TickType_t xLastWakeTime; - const TickType_t xSolenoidFrequency = SOLENOID_TIMER_INT_FREQ; // in ticks (typically ms) - uint16_t solenoid_delay_counter = 0; - xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time. - while (true) { // don't ever return from this or the task dies + int32_t current_position[N_AXIS]; // copy of current location + float m_pos[N_AXIS]; // machine position in mm + TickType_t xLastWakeTime; + const TickType_t xSolenoidFrequency = SOLENOID_TIMER_INT_FREQ; // in ticks (typically ms) + uint16_t solenoid_delay_counter = 0; + xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time. + while (true) { // don't ever return from this or the task dies if (!solenoid_pen_enable) { solenoid_delay_counter++; solenoid_pen_enable = (solenoid_delay_counter > SOLENOID_TURNON_DELAY); } else { - memcpy(current_position, sys_position, sizeof(sys_position)); // get current position in step - system_convert_array_steps_to_mpos(m_pos, current_position); // convert to millimeters - calc_solenoid(m_pos[Z_AXIS]); // calculate kinematics and move the servos + memcpy(current_position, sys_position, sizeof(sys_position)); // get current position in step + system_convert_array_steps_to_mpos(m_pos, current_position); // convert to millimeters + calc_solenoid(m_pos[Z_AXIS]); // calculate kinematics and move the servos } vTaskDelayUntil(&xLastWakeTime, xSolenoidFrequency); } @@ -81,11 +81,11 @@ void solenoidSyncTask(void* pvParameters) { // calculate and set the PWM value for the servo void calc_solenoid(float penZ) { uint32_t solenoid_pen_pulse_len; - if (!solenoid_pen_enable) // only proceed if startup delay as expired + if (!solenoid_pen_enable) // only proceed if startup delay as expired return; if (penZ < 0 && (sys.state != STATE_ALARM)) { // alarm also makes it go up - solenoide_hold_count = 0; // reset this count - solenoid_pen_pulse_len = 0; // + solenoide_hold_count = 0; // reset this count + solenoid_pen_pulse_len = 0; // } else { if (solenoide_hold_count < SOLENOID_PULSE_LEN_HOLD) { solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_UP; @@ -105,4 +105,3 @@ void calc_solenoid(float penZ) { } #endif - diff --git a/Grbl_Esp32/solenoid_pen.h b/Grbl_Esp32/solenoid_pen.h index 8a28fd0e..69a1d51a 100644 --- a/Grbl_Esp32/solenoid_pen.h +++ b/Grbl_Esp32/solenoid_pen.h @@ -35,34 +35,34 @@ */ #ifndef SOLENOID_PWM_FREQ - #define SOLENOID_PWM_FREQ 5000 +# define SOLENOID_PWM_FREQ 5000 #endif #ifndef SOLENOID_PWM_RES_BITS - #define SOLENOID_PWM_RES_BITS 8 +# define SOLENOID_PWM_RES_BITS 8 #endif #ifndef SOLENOID_TURNON_DELAY - #define SOLENOID_TURNON_DELAY (SOLENOID_TIMER_INT_FREQ/2) +# define SOLENOID_TURNON_DELAY (SOLENOID_TIMER_INT_FREQ / 2) #endif #ifndef SOLENOID_PULSE_LEN_UP - #define SOLENOID_PULSE_LEN_UP 255 +# define SOLENOID_PULSE_LEN_UP 255 #endif #ifndef SOLENOID_HOLD_DELAY - #define SOLENOID_HOLD_DELAY (SOLENOID_TIMER_INT_FREQ/2) // in task counts...after this delay power will change to hold level +# define SOLENOID_HOLD_DELAY (SOLENOID_TIMER_INT_FREQ / 2) // in task counts...after this delay power will change to hold level #endif #ifndef SOLENOID_PULSE_LEN_HOLD - #define SOLENOID_PULSE_LEN_HOLD 80 // solenoid hold level ... typically a lower value to prevent overheating +# define SOLENOID_PULSE_LEN_HOLD 80 // solenoid hold level ... typically a lower value to prevent overheating #endif #ifndef SOLENOID_TIMER_INT_FREQ - #define SOLENOID_TIMER_INT_FREQ 50 +# define SOLENOID_TIMER_INT_FREQ 50 #endif - void solenoid_init(); - void solenoid_disable(); - void solenoidSyncTask(void* pvParameters); - void calc_solenoid(float penZ); +void solenoid_init(); +void solenoid_disable(); +void solenoidSyncTask(void* pvParameters); +void calc_solenoid(float penZ); diff --git a/Grbl_Esp32/stepper.cpp b/Grbl_Esp32/stepper.cpp index ad8e54cd..96e1095d 100644 --- a/Grbl_Esp32/stepper.cpp +++ b/Grbl_Esp32/stepper.cpp @@ -34,8 +34,8 @@ typedef struct { uint32_t steps[N_AXIS]; uint32_t step_event_count; - uint8_t direction_bits; - uint8_t is_pwm_rate_adjusted; // Tracks motions that require constant laser power/rate + uint8_t direction_bits; + uint8_t is_pwm_rate_adjusted; // Tracks motions that require constant laser power/rate } st_block_t; static st_block_t st_block_buffer[SEGMENT_BUFFER_SIZE - 1]; @@ -48,9 +48,9 @@ typedef struct { uint16_t cycles_per_tick; // Step distance traveled per ISR tick, aka step rate. uint8_t st_block_index; // Stepper block data index. Uses this information to execute this segment. #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING - uint8_t amass_level; // Indicates AMASS level for the ISR to execute this segment + uint8_t amass_level; // Indicates AMASS level for the ISR to execute this segment #else - uint8_t prescaler; // Without AMASS, a prescaler is required to adjust for slow timing. + uint8_t prescaler; // Without AMASS, a prescaler is required to adjust for slow timing. #endif uint16_t spindle_rpm; // TODO get rid of this. } segment_t; @@ -59,42 +59,44 @@ static segment_t segment_buffer[SEGMENT_BUFFER_SIZE]; // Stepper ISR data struct. Contains the running data for the main stepper ISR. typedef struct { // Used by the bresenham line algorithm - uint32_t counter_x, // Counter variables for the bresenham line tracer - counter_y, - counter_z + uint32_t counter_x, // Counter variables for the bresenham line tracer + counter_y, counter_z #if (N_AXIS > A_AXIS) - , counter_a + , + counter_a #endif #if (N_AXIS > B_AXIS) - , counter_b + , + counter_b #endif #if (N_AXIS > C_AXIS) - , counter_c + , + counter_c #endif - ; + ; #ifdef STEP_PULSE_DELAY uint8_t step_bits; // Stores out_bits output to complete the step pulse delay #endif uint8_t execute_step; // Flags step execution for each interrupt. uint8_t step_pulse_time; // Step pulse reset time after step rise - uint8_t step_outbits; // The next stepping-bits to be output + uint8_t step_outbits; // The next stepping-bits to be output uint8_t dir_outbits; #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING uint32_t steps[N_AXIS]; #endif - uint16_t step_count; // Steps remaining in line segment motion - uint8_t exec_block_index; // Tracks the current st_block index. Change indicates new block. - st_block_t* exec_block; // Pointer to the block data for the segment being executed - segment_t* exec_segment; // Pointer to the segment being executed + uint16_t step_count; // Steps remaining in line segment motion + uint8_t exec_block_index; // Tracks the current st_block index. Change indicates new block. + st_block_t* exec_block; // Pointer to the block data for the segment being executed + segment_t* exec_segment; // Pointer to the segment being executed } stepper_t; static stepper_t st; // Step segment ring buffer indices static volatile uint8_t segment_buffer_tail; -static uint8_t segment_buffer_head; -static uint8_t segment_next_head; +static uint8_t segment_buffer_head; +static uint8_t segment_next_head; // Step and direction port invert masks. static uint8_t step_port_invert_mask; @@ -105,12 +107,12 @@ static volatile uint8_t busy; // Pointers for the step segment being prepped from the planner buffer. Accessed only by the // main program. Pointers may be planning segments or planner blocks ahead of what being executed. -static plan_block_t* pl_block; // Pointer to the planner block being prepped -static st_block_t* st_prep_block; // Pointer to the stepper block data being prepped +static plan_block_t* pl_block; // Pointer to the planner block being prepped +static st_block_t* st_prep_block; // Pointer to the stepper block data being prepped // esp32 work around for diable in main loop -uint64_t stepper_idle_counter; // used to count down until time to disable stepper drivers -bool stepper_idle; +uint64_t stepper_idle_counter; // used to count down until time to disable stepper drivers +bool stepper_idle; // Segment preparation data struct. Contains all the necessary information to compute new segments // based on the current executing planner block. @@ -125,30 +127,27 @@ typedef struct { #ifdef PARKING_ENABLE uint8_t last_st_block_index; - float last_steps_remaining; - float last_step_per_mm; - float last_dt_remainder; + float last_steps_remaining; + float last_step_per_mm; + float last_dt_remainder; #endif - uint8_t ramp_type; // Current segment ramp state - float mm_complete; // End of velocity profile from end of current planner block in (mm). + uint8_t ramp_type; // Current segment ramp state + float mm_complete; // End of velocity profile from end of current planner block in (mm). // NOTE: This value must coincide with a step(no mantissa) when converted. - float current_speed; // Current speed at the end of the segment buffer (mm/min) - float maximum_speed; // Maximum speed of executing block. Not always nominal speed. (mm/min) - float exit_speed; // Exit speed of executing block (mm/min) - float accelerate_until; // Acceleration ramp end measured from end of block (mm) - float decelerate_after; // Deceleration ramp start measured from end of block (mm) + float current_speed; // Current speed at the end of the segment buffer (mm/min) + float maximum_speed; // Maximum speed of executing block. Not always nominal speed. (mm/min) + float exit_speed; // Exit speed of executing block (mm/min) + float accelerate_until; // Acceleration ramp end measured from end of block (mm) + float decelerate_after; // Deceleration ramp start measured from end of block (mm) - - float inv_rate; // Used by PWM laser mode to speed up segment calculations. + float inv_rate; // Used by PWM laser mode to speed up segment calculations. //uint16_t current_spindle_pwm; // todo remove float current_spindle_rpm; } st_prep_t; static st_prep_t prep; - - /* "The Stepper Driver Interrupt" - This timer interrupt is the workhorse of Grbl. Grbl employs the venerable Bresenham line algorithm to manage and exactly synchronize multi-axis moves. Unlike the popular DDA algorithm, the Bresenham algorithm is not susceptible to numerical @@ -205,7 +204,7 @@ static st_prep_t prep; */ #ifdef USE_RMT_STEPS - inline IRAM_ATTR static void stepperRMT_Outputs(); +inline IRAM_ATTR static void stepperRMT_Outputs(); #endif static void stepper_pulse_func(); @@ -213,18 +212,19 @@ static void stepper_pulse_func(); // TODO: Replace direct updating of the int32 position counters in the ISR somehow. Perhaps use smaller // int8 variables and update position counters only when a segment completes. This can get complicated // with probing and homing cycles that require true real-time positions. -void IRAM_ATTR onStepperDriverTimer(void* para) { // ISR It is time to take a step ======================================================================================= +void IRAM_ATTR onStepperDriverTimer( + void* para) { // ISR It is time to take a step ======================================================================================= //const int timer_idx = (int)para; // get the timer index TIMERG0.int_clr_timers.t0 = 1; if (busy) { - return; // The busy-flag is used to avoid reentering this interrupt + return; // The busy-flag is used to avoid reentering this interrupt } busy = true; stepper_pulse_func(); TIMERG0.hw_timer[STEP_TIMER_INDEX].config.alarm_en = TIMER_ALARM_EN; - busy = false; + busy = false; } /** @@ -240,9 +240,9 @@ static void stepper_pulse_func() { stepperRMT_Outputs(); #else set_stepper_pins_on(st.step_outbits); -#ifndef USE_I2S_OUT_STREAM +# ifndef USE_I2S_OUT_STREAM uint64_t step_pulse_start_time = esp_timer_get_time(); -#endif +# endif #endif // some motor objects, like unipolar, handle steps themselves @@ -256,12 +256,12 @@ static void stepper_pulse_func() { st.exec_segment = &segment_buffer[segment_buffer_tail]; // Initialize step segment timing per step and load number of steps to execute. Stepper_Timer_WritePeriod(st.exec_segment->cycles_per_tick); - st.step_count = st.exec_segment->n_step; // NOTE: Can sometimes be zero when moving slow. + st.step_count = st.exec_segment->n_step; // NOTE: Can sometimes be zero when moving slow. // If the new segment starts a new planner block, initialize stepper variables and counters. // NOTE: When the segment data index changes, this indicates a new planner block. if (st.exec_block_index != st.exec_segment->st_block_index) { st.exec_block_index = st.exec_segment->st_block_index; - st.exec_block = &st_block_buffer[st.exec_block_index]; + st.exec_block = &st_block_buffer[st.exec_block_index]; // Initialize Bresenham line and distance counters st.counter_x = st.counter_y = st.counter_z = (st.exec_block->step_event_count >> 1); // TODO ABC @@ -272,15 +272,15 @@ static void stepper_pulse_func() { st.steps[X_AXIS] = st.exec_block->steps[X_AXIS] >> st.exec_segment->amass_level; st.steps[Y_AXIS] = st.exec_block->steps[Y_AXIS] >> st.exec_segment->amass_level; st.steps[Z_AXIS] = st.exec_block->steps[Z_AXIS] >> st.exec_segment->amass_level; -#if (N_AXIS > A_AXIS) +# if (N_AXIS > A_AXIS) st.steps[A_AXIS] = st.exec_block->steps[A_AXIS] >> st.exec_segment->amass_level; -#endif -#if (N_AXIS > B_AXIS) +# endif +# if (N_AXIS > B_AXIS) st.steps[B_AXIS] = st.exec_block->steps[B_AXIS] >> st.exec_segment->amass_level; -#endif -#if (N_AXIS > C_AXIS) +# endif +# if (N_AXIS > C_AXIS) st.steps[C_AXIS] = st.exec_block->steps[C_AXIS] >> st.exec_segment->amass_level; -#endif +# endif #endif // Set real-time spindle output as segment is loaded, just prior to the first step. spindle->set_rpm(st.exec_segment->spindle_rpm); @@ -293,8 +293,8 @@ static void stepper_pulse_func() { spindle->set_rpm(0); } - system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end - return; // Nothing to do but exit. + system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end + return; // Nothing to do but exit. } } // Check probing state. @@ -343,48 +343,54 @@ static void stepper_pulse_func() { sys_position[Z_AXIS]++; } #if (N_AXIS > A_AXIS) -#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING +# ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING st.counter_a += st.steps[A_AXIS]; -#else +# else st.counter_a += st.exec_block->steps[A_AXIS]; -#endif +# endif if (st.counter_a > st.exec_block->step_event_count) { st.step_outbits |= bit(A_AXIS); st.counter_a -= st.exec_block->step_event_count; - if (st.exec_block->direction_bits & bit(A_AXIS)) sys_position[A_AXIS]--; - else sys_position[A_AXIS]++; + if (st.exec_block->direction_bits & bit(A_AXIS)) + sys_position[A_AXIS]--; + else + sys_position[A_AXIS]++; } #endif #if (N_AXIS > B_AXIS) -#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING +# ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING st.counter_b += st.steps[B_AXIS]; -#else +# else st.counter_b += st.exec_block->steps[B_AXIS]; -#endif +# endif if (st.counter_b > st.exec_block->step_event_count) { st.step_outbits |= bit(B_AXIS); st.counter_b -= st.exec_block->step_event_count; - if (st.exec_block->direction_bits & bit(B_AXIS)) sys_position[B_AXIS]--; - else sys_position[B_AXIS]++; + if (st.exec_block->direction_bits & bit(B_AXIS)) + sys_position[B_AXIS]--; + else + sys_position[B_AXIS]++; } #endif #if (N_AXIS > C_AXIS) -#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING +# ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING st.counter_c += st.steps[C_AXIS]; -#else +# else st.counter_c += st.exec_block->steps[C_AXIS]; -#endif +# endif if (st.counter_c > st.exec_block->step_event_count) { st.step_outbits |= bit(C_AXIS); st.counter_c -= st.exec_block->step_event_count; - if (st.exec_block->direction_bits & bit(C_AXIS)) sys_position[C_AXIS]--; - else sys_position[C_AXIS]++; + if (st.exec_block->direction_bits & bit(C_AXIS)) + sys_position[C_AXIS]--; + else + sys_position[C_AXIS]++; } #endif // During a homing cycle, lock out and prevent desired axes from moving. if (sys.state == STATE_HOMING) st.step_outbits &= sys.homing_axis_lock; - st.step_count--; // Decrement step events count + st.step_count--; // Decrement step events count if (st.step_count == 0) { // Segment is complete. Discard current segment and advance segment indexing. st.exec_segment = NULL; @@ -393,28 +399,27 @@ static void stepper_pulse_func() { } #ifndef USE_RMT_STEPS -#ifdef USE_I2S_OUT_STREAM +# ifdef USE_I2S_OUT_STREAM // // Generate pulse (at least one pulse) // The pulse resolution is limited by I2S_OUT_USEC_PER_PULSE // st.step_outbits ^= step_port_invert_mask; // Apply step port invert mask i2s_out_push_sample(pulse_microseconds->get() / I2S_OUT_USEC_PER_PULSE); - set_stepper_pins_on(0); // turn all off -#else + set_stepper_pins_on(0); // turn all off +# else st.step_outbits ^= step_port_invert_mask; // Apply step port invert mask // wait for step pulse time to complete...some of it should have expired during code above while (esp_timer_get_time() - step_pulse_start_time < pulse_microseconds->get()) { - NOP(); // spin here until time to turn off step + NOP(); // spin here until time to turn off step } - set_stepper_pins_on(0); // turn all off -#endif + set_stepper_pins_on(0); // turn all off +# endif #endif return; } void stepper_init() { - grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Axis count %d", N_AXIS); // make the step pins outputs #ifdef USE_RMT_STEPS @@ -441,11 +446,8 @@ void stepper_init() { timer_enable_intr(STEP_TIMER_GROUP, STEP_TIMER_INDEX); timer_isr_register(STEP_TIMER_GROUP, STEP_TIMER_INDEX, onStepperDriverTimer, NULL, 0, NULL); #endif - } - - // enabled. Startup init and limits call this function but shouldn't start the cycle. void st_wake_up() { //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "st_wake_up"); @@ -457,7 +459,7 @@ void st_wake_up() { // Initialize step pulse timing from settings. Here to ensure updating after re-writing. #ifdef STEP_PULSE_DELAY // Step pulse delay handling is not require with ESP32...the RMT function does it. -#else // Normal operation +#else // Normal operation // Set step pulse time. Ad hoc computation from oscilloscope. Uses two's complement. st.step_pulse_time = -(((pulse_microseconds->get() - 2) * TICKS_PER_MICROSECOND) >> 3); #endif @@ -478,198 +480,194 @@ void st_reset() { // Initialize stepper algorithm variables. memset(&prep, 0, sizeof(st_prep_t)); memset(&st, 0, sizeof(stepper_t)); - st.exec_segment = NULL; - pl_block = NULL; // Planner block pointer used by segment buffer + st.exec_segment = NULL; + pl_block = NULL; // Planner block pointer used by segment buffer segment_buffer_tail = 0; - segment_buffer_head = 0; // empty = tail - segment_next_head = 1; - busy = false; + segment_buffer_head = 0; // empty = tail + segment_next_head = 1; + busy = false; st_generate_step_dir_invert_masks(); - st.dir_outbits = dir_port_invert_mask; // Initialize direction bits to default. + st.dir_outbits = dir_port_invert_mask; // Initialize direction bits to default. // TODO do we need to turn step pins off? } - void set_stepper_pins_on(uint8_t onMask) { - onMask ^= step_invert_mask->get(); // invert pins as required by invert mask + onMask ^= step_invert_mask->get(); // invert pins as required by invert mask #ifdef X_STEP_PIN -#ifndef X2_STEP_PIN // if not a ganged axis +# ifndef X2_STEP_PIN // if not a ganged axis digitalWrite(X_STEP_PIN, (onMask & bit(X_AXIS))); -#else // is a ganged axis +# else // is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) digitalWrite(X_STEP_PIN, (onMask & bit(X_AXIS))); if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) digitalWrite(X2_STEP_PIN, (onMask & bit(X_AXIS))); -#endif +# endif #endif #ifdef Y_STEP_PIN -#ifndef Y2_STEP_PIN // if not a ganged axis +# ifndef Y2_STEP_PIN // if not a ganged axis digitalWrite(Y_STEP_PIN, (onMask & bit(Y_AXIS))); -#else // is a ganged axis +# else // is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) digitalWrite(Y_STEP_PIN, (onMask & bit(Y_AXIS))); if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) digitalWrite(Y2_STEP_PIN, (onMask & bit(Y_AXIS))); +# endif #endif -#endif - #ifdef Z_STEP_PIN -#ifndef Z2_STEP_PIN // if not a ganged axis +# ifndef Z2_STEP_PIN // if not a ganged axis digitalWrite(Z_STEP_PIN, (onMask & bit(Z_AXIS))); -#else // is a ganged axis +# else // is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) digitalWrite(Z_STEP_PIN, (onMask & bit(Z_AXIS))); if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) digitalWrite(Z2_STEP_PIN, (onMask & bit(Z_AXIS))); -#endif +# endif #endif #ifdef A_STEP_PIN -#ifndef A2_STEP_PIN // if not a ganged axis +# ifndef A2_STEP_PIN // if not a ganged axis digitalWrite(A_STEP_PIN, (onMask & bit(A_AXIS))); -#else // is a ganged axis +# else // is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) digitalWrite(A_STEP_PIN, (onMask & bit(A_AXIS))); if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) digitalWrite(A2_STEP_PIN, (onMask & bit(A_AXIS))); -#endif +# endif #endif #ifdef B_STEP_PIN -#ifndef B2_STEP_PIN // if not a ganged axis +# ifndef B2_STEP_PIN // if not a ganged axis digitalWrite(B_STEP_PIN, (onMask & bit(B_AXIS))); -#else // is a ganged axis +# else // is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) digitalWrite(B_STEP_PIN, (onMask & bit(B_AXIS))); if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) digitalWrite(B2_STEP_PIN, (onMask & bit(B_AXIS))); -#endif +# endif #endif #ifdef C_STEP_PIN -#ifndef C2_STEP_PIN // if not a ganged axis +# ifndef C2_STEP_PIN // if not a ganged axis digitalWrite(C_STEP_PIN, (onMask & bit(C_AXIS))); -#else // is a ganged axis +# else // is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) digitalWrite(C_STEP_PIN, (onMask & bit(C_AXIS))); if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) digitalWrite(C2_STEP_PIN, (onMask & bit(C_AXIS))); -#endif +# endif #endif } //#endif #ifdef USE_RMT_STEPS inline IRAM_ATTR static void stepperRMT_Outputs() { -#ifdef X_STEP_PIN +# ifdef X_STEP_PIN if (st.step_outbits & bit(X_AXIS)) { -#ifndef X2_STEP_PIN // if not a ganged axis +# ifndef X2_STEP_PIN // if not a ganged axis RMT.conf_ch[rmt_chan_num[X_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[X_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; -#else // it is a ganged axis + RMT.conf_ch[rmt_chan_num[X_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; +# else // it is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) { RMT.conf_ch[rmt_chan_num[X_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[X_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[X_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; } if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) { RMT.conf_ch[rmt_chan_num[X_AXIS][GANGED_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[X_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[X_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; } -#endif +# endif } -#endif -#ifdef Y_STEP_PIN +# endif +# ifdef Y_STEP_PIN if (st.step_outbits & bit(Y_AXIS)) { -#ifndef Y2_STEP_PIN // if not a ganged axis +# ifndef Y2_STEP_PIN // if not a ganged axis RMT.conf_ch[rmt_chan_num[Y_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[Y_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; -#else // it is a ganged axis + RMT.conf_ch[rmt_chan_num[Y_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; +# else // it is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) { RMT.conf_ch[rmt_chan_num[Y_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[Y_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[Y_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; } if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) { RMT.conf_ch[rmt_chan_num[Y_AXIS][GANGED_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[Y_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[Y_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; } -#endif +# endif } -#endif +# endif -#ifdef Z_STEP_PIN +# ifdef Z_STEP_PIN if (st.step_outbits & bit(Z_AXIS)) { -#ifndef Z2_STEP_PIN // if not a ganged axis +# ifndef Z2_STEP_PIN // if not a ganged axis RMT.conf_ch[rmt_chan_num[Z_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[Z_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; -#else // it is a ganged axis + RMT.conf_ch[rmt_chan_num[Z_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; +# else // it is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) { RMT.conf_ch[rmt_chan_num[Z_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[Z_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[Z_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; } if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) { RMT.conf_ch[rmt_chan_num[Z_AXIS][GANGED_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[Z_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[Z_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; } -#endif +# endif } -#endif +# endif -#ifdef A_STEP_PIN +# ifdef A_STEP_PIN if (st.step_outbits & bit(A_AXIS)) { -#ifndef A2_STEP_PIN // if not a ganged axis +# ifndef A2_STEP_PIN // if not a ganged axis RMT.conf_ch[rmt_chan_num[A_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[A_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; -#else // it is a ganged axis + RMT.conf_ch[rmt_chan_num[A_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; +# else // it is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) { RMT.conf_ch[rmt_chan_num[A_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[A_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[A_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; } if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) { RMT.conf_ch[rmt_chan_num[A_AXIS][GANGED_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[A_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[A_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; } -#endif +# endif } -#endif +# endif -#ifdef B_STEP_PIN +# ifdef B_STEP_PIN if (st.step_outbits & bit(B_AXIS)) { -#ifndef Z2_STEP_PIN // if not a ganged axis +# ifndef Z2_STEP_PIN // if not a ganged axis RMT.conf_ch[rmt_chan_num[B_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[B_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; -#else // it is a ganged axis + RMT.conf_ch[rmt_chan_num[B_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; +# else // it is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) { RMT.conf_ch[rmt_chan_num[B_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[B_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[B_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; } if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) { RMT.conf_ch[rmt_chan_num[B_AXIS][GANGED_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[B_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[B_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; } -#endif +# endif } -#endif +# endif -#ifdef C_STEP_PIN +# ifdef C_STEP_PIN if (st.step_outbits & bit(C_AXIS)) { -#ifndef Z2_STEP_PIN // if not a ganged axis +# ifndef Z2_STEP_PIN // if not a ganged axis RMT.conf_ch[rmt_chan_num[C_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[C_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; -#else // it is a ganged axis + RMT.conf_ch[rmt_chan_num[C_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; +# else // it is a ganged axis if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_A)) { RMT.conf_ch[rmt_chan_num[C_AXIS][PRIMARY_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[C_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[C_AXIS][PRIMARY_MOTOR]].conf1.tx_start = 1; } if ((ganged_mode == SQUARING_MODE_DUAL) || (ganged_mode == SQUARING_MODE_B)) { RMT.conf_ch[rmt_chan_num[C_AXIS][GANGED_MOTOR]].conf1.mem_rd_rst = 1; - RMT.conf_ch[rmt_chan_num[C_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; + RMT.conf_ch[rmt_chan_num[C_AXIS][GANGED_MOTOR]].conf1.tx_start = 1; } -#endif +# endif } -#endif - - +# endif } #endif @@ -686,8 +684,8 @@ void st_go_idle() { if (sys.state == STATE_SLEEP || sys_rt_exec_alarm) { motors_set_disable(true); } else { - stepper_idle = true; // esp32 work around for disable in main loop - stepper_idle_counter = esp_timer_get_time() + (stepper_idle_lock_time->get() * 1000); // * 1000 because the time is in uSecs + stepper_idle = true; // esp32 work around for disable in main loop + stepper_idle_counter = esp_timer_get_time() + (stepper_idle_lock_time->get() * 1000); // * 1000 because the time is in uSecs // after idle countdown will be disabled in protocol loop } } else @@ -698,10 +696,10 @@ void st_go_idle() { // Called by planner_recalculate() when the executing block is updated by the new plan. void st_update_plan_block_parameters() { - if (pl_block != NULL) { // Ignore if at start of a new block. + if (pl_block != NULL) { // Ignore if at start of a new block. prep.recalculate_flag |= PREP_FLAG_RECALCULATE; - pl_block->entry_speed_sqr = prep.current_speed * prep.current_speed; // Update entry speed. - pl_block = NULL; // Flag st_prep_segment() to load and check active velocity profile. + pl_block->entry_speed_sqr = prep.current_speed * prep.current_speed; // Update entry speed. + pl_block = NULL; // Flag st_prep_segment() to load and check active velocity profile. } } @@ -710,32 +708,31 @@ void st_update_plan_block_parameters() { void st_parking_setup_buffer() { // Store step execution data of partially completed block, if necessary. if (prep.recalculate_flag & PREP_FLAG_HOLD_PARTIAL_BLOCK) { - prep.last_st_block_index = prep.st_block_index; + prep.last_st_block_index = prep.st_block_index; prep.last_steps_remaining = prep.steps_remaining; - prep.last_dt_remainder = prep.dt_remainder; - prep.last_step_per_mm = prep.step_per_mm; + prep.last_dt_remainder = prep.dt_remainder; + prep.last_step_per_mm = prep.step_per_mm; } // Set flags to execute a parking motion prep.recalculate_flag |= PREP_FLAG_PARKING; prep.recalculate_flag &= ~(PREP_FLAG_RECALCULATE); - pl_block = NULL; // Always reset parking motion to reload new block. + pl_block = NULL; // Always reset parking motion to reload new block. } - // Restores the step segment buffer to the normal run state after a parking motion. void st_parking_restore_buffer() { // Restore step execution data and flags of partially completed block, if necessary. if (prep.recalculate_flag & PREP_FLAG_HOLD_PARTIAL_BLOCK) { - st_prep_block = &st_block_buffer[prep.last_st_block_index]; - prep.st_block_index = prep.last_st_block_index; - prep.steps_remaining = prep.last_steps_remaining; - prep.dt_remainder = prep.last_dt_remainder; - prep.step_per_mm = prep.last_step_per_mm; + st_prep_block = &st_block_buffer[prep.last_st_block_index]; + prep.st_block_index = prep.last_st_block_index; + prep.steps_remaining = prep.last_steps_remaining; + prep.dt_remainder = prep.last_dt_remainder; + prep.step_per_mm = prep.last_step_per_mm; prep.recalculate_flag = (PREP_FLAG_HOLD_PARTIAL_BLOCK | PREP_FLAG_RECALCULATE); - prep.req_mm_increment = REQ_MM_INCREMENT_SCALAR / prep.step_per_mm; // Recompute this value. + prep.req_mm_increment = REQ_MM_INCREMENT_SCALAR / prep.step_per_mm; // Recompute this value. } else prep.recalculate_flag = false; - pl_block = NULL; // Set to reload next block. + pl_block = NULL; // Set to reload next block. } #endif @@ -752,7 +749,7 @@ void st_generate_step_dir_invert_masks() { */ // simpler with ESP32, but let's do it here for easier change management step_port_invert_mask = step_invert_mask->get(); - dir_port_invert_mask = dir_invert_mask->get(); + dir_port_invert_mask = dir_invert_mask->get(); } // Increments the step segment buffer block data ring buffer. @@ -780,7 +777,7 @@ void st_prep_buffer() { // Block step prep buffer, while in a suspend state and there is no suspend motion to execute. if (bit_istrue(sys.step_control, STEP_CONTROL_END_MOTION)) return; - while (segment_buffer_tail != segment_next_head) { // Check if we need to fill the buffer. + while (segment_buffer_tail != segment_next_head) { // Check if we need to fill the buffer. // Determine if we need to load a new planner block or if the block needs to be recomputed. if (pl_block == NULL) { // Query planner for a queued block @@ -789,7 +786,7 @@ void st_prep_buffer() { else pl_block = plan_get_current_block(); if (pl_block == NULL) { - return; // No planner blocks. Exit. + return; // No planner blocks. Exit. } // Check if we need to only recompute the velocity profile or load a new block. if (prep.recalculate_flag & PREP_FLAG_RECALCULATE) { @@ -807,7 +804,7 @@ void st_prep_buffer() { // Prepare and copy Bresenham algorithm segment data from the new planner block, so that // when the segment buffer completes the planner block, it may be discarded when the // segment buffer finishes the prepped block, but the stepper ISR is still executing it. - st_prep_block = &st_block_buffer[prep.st_block_index]; + st_prep_block = &st_block_buffer[prep.st_block_index]; st_prep_block->direction_bits = pl_block->direction_bits; uint8_t idx; #ifndef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING @@ -823,27 +820,25 @@ void st_prep_buffer() { st_prep_block->step_event_count = pl_block->step_event_count << MAX_AMASS_LEVEL; #endif // Initialize segment buffer data for generating the segments. - prep.steps_remaining = (float)pl_block->step_event_count; - prep.step_per_mm = prep.steps_remaining / pl_block->millimeters; + prep.steps_remaining = (float)pl_block->step_event_count; + prep.step_per_mm = prep.steps_remaining / pl_block->millimeters; prep.req_mm_increment = REQ_MM_INCREMENT_SCALAR / prep.step_per_mm; - prep.dt_remainder = 0.0; // Reset for new segment block + prep.dt_remainder = 0.0; // Reset for new segment block if ((sys.step_control & STEP_CONTROL_EXECUTE_HOLD) || (prep.recalculate_flag & PREP_FLAG_DECEL_OVERRIDE)) { // New block loaded mid-hold. Override planner block entry speed to enforce deceleration. - prep.current_speed = prep.exit_speed; + prep.current_speed = prep.exit_speed; pl_block->entry_speed_sqr = prep.exit_speed * prep.exit_speed; prep.recalculate_flag &= ~(PREP_FLAG_DECEL_OVERRIDE); } else prep.current_speed = sqrt(pl_block->entry_speed_sqr); - - if (spindle->isRateAdjusted() ){ // laser_mode->get() { + if (spindle->isRateAdjusted()) { // laser_mode->get() { if (pl_block->condition & PL_COND_FLAG_SPINDLE_CCW) { // Pre-compute inverse programmed rate to speed up PWM updating per step segment. - prep.inv_rate = 1.0 / pl_block->programmed_rate; + prep.inv_rate = 1.0 / pl_block->programmed_rate; st_prep_block->is_pwm_rate_adjusted = true; } } - } /* --------------------------------------------------------------------------------- Compute the velocity profile of a new planner block based on its entry and exit @@ -851,9 +846,9 @@ void st_prep_buffer() { planner has updated it. For a commanded forced-deceleration, such as from a feed hold, override the planner velocities and decelerate to the target exit speed. */ - prep.mm_complete = 0.0; // Default velocity profile complete at 0.0mm from end of block. + prep.mm_complete = 0.0; // Default velocity profile complete at 0.0mm from end of block. float inv_2_accel = 0.5 / pl_block->acceleration; - if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) { // [Forced Deceleration to Zero Velocity] + if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) { // [Forced Deceleration to Zero Velocity] // Compute velocity profile parameters for a feed hold in-progress. This profile overrides // the planner block profile, enforcing a deceleration to zero speed. prep.ramp_type = RAMP_DECEL; @@ -863,48 +858,47 @@ void st_prep_buffer() { // Deceleration through entire planner block. End of feed hold is not in this block. prep.exit_speed = sqrt(pl_block->entry_speed_sqr - 2 * pl_block->acceleration * pl_block->millimeters); } else { - prep.mm_complete = decel_dist; // End of feed hold. - prep.exit_speed = 0.0; + prep.mm_complete = decel_dist; // End of feed hold. + prep.exit_speed = 0.0; } - } else { // [Normal Operation] + } else { // [Normal Operation] // Compute or recompute velocity profile parameters of the prepped planner block. - prep.ramp_type = RAMP_ACCEL; // Initialize as acceleration ramp. + prep.ramp_type = RAMP_ACCEL; // Initialize as acceleration ramp. prep.accelerate_until = pl_block->millimeters; float exit_speed_sqr; float nominal_speed; if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) { - prep.exit_speed = exit_speed_sqr = 0.0; // Enforce stop at end of system motion. + prep.exit_speed = exit_speed_sqr = 0.0; // Enforce stop at end of system motion. } else { - exit_speed_sqr = plan_get_exec_block_exit_speed_sqr(); + exit_speed_sqr = plan_get_exec_block_exit_speed_sqr(); prep.exit_speed = sqrt(exit_speed_sqr); } - nominal_speed = plan_compute_profile_nominal_speed(pl_block); - float nominal_speed_sqr = nominal_speed * nominal_speed; - float intersect_distance = - 0.5 * (pl_block->millimeters + inv_2_accel * (pl_block->entry_speed_sqr - exit_speed_sqr)); - if (pl_block->entry_speed_sqr > nominal_speed_sqr) { // Only occurs during override reductions. + nominal_speed = plan_compute_profile_nominal_speed(pl_block); + float nominal_speed_sqr = nominal_speed * nominal_speed; + float intersect_distance = 0.5 * (pl_block->millimeters + inv_2_accel * (pl_block->entry_speed_sqr - exit_speed_sqr)); + if (pl_block->entry_speed_sqr > nominal_speed_sqr) { // Only occurs during override reductions. prep.accelerate_until = pl_block->millimeters - inv_2_accel * (pl_block->entry_speed_sqr - nominal_speed_sqr); - if (prep.accelerate_until <= 0.0) { // Deceleration-only. + if (prep.accelerate_until <= 0.0) { // Deceleration-only. prep.ramp_type = RAMP_DECEL; // prep.decelerate_after = pl_block->millimeters; // prep.maximum_speed = prep.current_speed; // Compute override block exit speed since it doesn't match the planner exit speed. prep.exit_speed = sqrt(pl_block->entry_speed_sqr - 2 * pl_block->acceleration * pl_block->millimeters); - prep.recalculate_flag |= PREP_FLAG_DECEL_OVERRIDE; // Flag to load next block as deceleration override. + prep.recalculate_flag |= PREP_FLAG_DECEL_OVERRIDE; // Flag to load next block as deceleration override. // TODO: Determine correct handling of parameters in deceleration-only. // Can be tricky since entry speed will be current speed, as in feed holds. // Also, look into near-zero speed handling issues with this. } else { // Decelerate to cruise or cruise-decelerate types. Guaranteed to intersect updated plan. prep.decelerate_after = inv_2_accel * (nominal_speed_sqr - exit_speed_sqr); - prep.maximum_speed = nominal_speed; - prep.ramp_type = RAMP_DECEL_OVERRIDE; + prep.maximum_speed = nominal_speed; + prep.ramp_type = RAMP_DECEL_OVERRIDE; } } else if (intersect_distance > 0.0) { - if (intersect_distance < pl_block->millimeters) { // Either trapezoid or triangle types + if (intersect_distance < pl_block->millimeters) { // Either trapezoid or triangle types // NOTE: For acceleration-cruise and cruise-only types, following calculation will be 0.0. prep.decelerate_after = inv_2_accel * (nominal_speed_sqr - exit_speed_sqr); - if (prep.decelerate_after < intersect_distance) { // Trapezoid type + if (prep.decelerate_after < intersect_distance) { // Trapezoid type prep.maximum_speed = nominal_speed; if (pl_block->entry_speed_sqr == nominal_speed_sqr) { // Cruise-deceleration or cruise-only type. @@ -913,25 +907,24 @@ void st_prep_buffer() { // Full-trapezoid or acceleration-cruise types prep.accelerate_until -= inv_2_accel * (nominal_speed_sqr - pl_block->entry_speed_sqr); } - } else { // Triangle type + } else { // Triangle type prep.accelerate_until = intersect_distance; prep.decelerate_after = intersect_distance; - prep.maximum_speed = sqrt(2.0 * pl_block->acceleration * intersect_distance + exit_speed_sqr); + prep.maximum_speed = sqrt(2.0 * pl_block->acceleration * intersect_distance + exit_speed_sqr); } - } else { // Deceleration-only type + } else { // Deceleration-only type prep.ramp_type = RAMP_DECEL; // prep.decelerate_after = pl_block->millimeters; // prep.maximum_speed = prep.current_speed; } - } else { // Acceleration-only type + } else { // Acceleration-only type prep.accelerate_until = 0.0; // prep.decelerate_after = 0.0; prep.maximum_speed = prep.exit_speed; } } - bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); // Force update whenever updating block. - + bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); // Force update whenever updating block. } // Initialize new segment segment_t* prep_segment = &segment_buffer[segment_buffer_head]; @@ -951,90 +944,90 @@ void st_prep_buffer() { the end of planner block (typical) or mid-block at the end of a forced deceleration, such as from a feed hold. */ - float dt_max = DT_SEGMENT; // Maximum segment time - float dt = 0.0; // Initialize segment time - float time_var = dt_max; // Time worker variable - float mm_var; // mm-Distance worker variable - float speed_var; // Speed worker variable - float mm_remaining = pl_block->millimeters; // New segment distance from end of block. - float minimum_mm = mm_remaining - prep.req_mm_increment; // Guarantee at least one step. + float dt_max = DT_SEGMENT; // Maximum segment time + float dt = 0.0; // Initialize segment time + float time_var = dt_max; // Time worker variable + float mm_var; // mm-Distance worker variable + float speed_var; // Speed worker variable + float mm_remaining = pl_block->millimeters; // New segment distance from end of block. + float minimum_mm = mm_remaining - prep.req_mm_increment; // Guarantee at least one step. if (minimum_mm < 0.0) minimum_mm = 0.0; do { switch (prep.ramp_type) { - case RAMP_DECEL_OVERRIDE: - speed_var = pl_block->acceleration * time_var; - mm_var = time_var * (prep.current_speed - 0.5 * speed_var); - mm_remaining -= mm_var; - if ((mm_remaining < prep.accelerate_until) || (mm_var <= 0)) { - // Cruise or cruise-deceleration types only for deceleration override. - mm_remaining = prep.accelerate_until; // NOTE: 0.0 at EOB - time_var = 2.0 * (pl_block->millimeters - mm_remaining) / (prep.current_speed + prep.maximum_speed); - prep.ramp_type = RAMP_CRUISE; - prep.current_speed = prep.maximum_speed; - } else // Mid-deceleration override ramp. - prep.current_speed -= speed_var; - break; - case RAMP_ACCEL: - // NOTE: Acceleration ramp only computes during first do-while loop. - speed_var = pl_block->acceleration * time_var; - mm_remaining -= time_var * (prep.current_speed + 0.5 * speed_var); - if (mm_remaining < prep.accelerate_until) { // End of acceleration ramp. - // Acceleration-cruise, acceleration-deceleration ramp junction, or end of block. - mm_remaining = prep.accelerate_until; // NOTE: 0.0 at EOB - time_var = 2.0 * (pl_block->millimeters - mm_remaining) / (prep.current_speed + prep.maximum_speed); - if (mm_remaining == prep.decelerate_after) - prep.ramp_type = RAMP_DECEL; - else - prep.ramp_type = RAMP_CRUISE; - prep.current_speed = prep.maximum_speed; - } else // Acceleration only. - prep.current_speed += speed_var; - break; - case RAMP_CRUISE: - // NOTE: mm_var used to retain the last mm_remaining for incomplete segment time_var calculations. - // NOTE: If maximum_speed*time_var value is too low, round-off can cause mm_var to not change. To - // prevent this, simply enforce a minimum speed threshold in the planner. - mm_var = mm_remaining - prep.maximum_speed * time_var; - if (mm_var < prep.decelerate_after) { // End of cruise. - // Cruise-deceleration junction or end of block. - time_var = (mm_remaining - prep.decelerate_after) / prep.maximum_speed; - mm_remaining = prep.decelerate_after; // NOTE: 0.0 at EOB - prep.ramp_type = RAMP_DECEL; - } else // Cruising only. - mm_remaining = mm_var; - break; - default: // case RAMP_DECEL: - // NOTE: mm_var used as a misc worker variable to prevent errors when near zero speed. - speed_var = pl_block->acceleration * time_var; // Used as delta speed (mm/min) - if (prep.current_speed > speed_var) { // Check if at or below zero speed. - // Compute distance from end of segment to end of block. - mm_var = mm_remaining - time_var * (prep.current_speed - 0.5 * speed_var); // (mm) - if (mm_var > prep.mm_complete) { // Typical case. In deceleration ramp. - mm_remaining = mm_var; + case RAMP_DECEL_OVERRIDE: + speed_var = pl_block->acceleration * time_var; + mm_var = time_var * (prep.current_speed - 0.5 * speed_var); + mm_remaining -= mm_var; + if ((mm_remaining < prep.accelerate_until) || (mm_var <= 0)) { + // Cruise or cruise-deceleration types only for deceleration override. + mm_remaining = prep.accelerate_until; // NOTE: 0.0 at EOB + time_var = 2.0 * (pl_block->millimeters - mm_remaining) / (prep.current_speed + prep.maximum_speed); + prep.ramp_type = RAMP_CRUISE; + prep.current_speed = prep.maximum_speed; + } else // Mid-deceleration override ramp. prep.current_speed -= speed_var; - break; // Segment complete. Exit switch-case statement. Continue do-while loop. + break; + case RAMP_ACCEL: + // NOTE: Acceleration ramp only computes during first do-while loop. + speed_var = pl_block->acceleration * time_var; + mm_remaining -= time_var * (prep.current_speed + 0.5 * speed_var); + if (mm_remaining < prep.accelerate_until) { // End of acceleration ramp. + // Acceleration-cruise, acceleration-deceleration ramp junction, or end of block. + mm_remaining = prep.accelerate_until; // NOTE: 0.0 at EOB + time_var = 2.0 * (pl_block->millimeters - mm_remaining) / (prep.current_speed + prep.maximum_speed); + if (mm_remaining == prep.decelerate_after) + prep.ramp_type = RAMP_DECEL; + else + prep.ramp_type = RAMP_CRUISE; + prep.current_speed = prep.maximum_speed; + } else // Acceleration only. + prep.current_speed += speed_var; + break; + case RAMP_CRUISE: + // NOTE: mm_var used to retain the last mm_remaining for incomplete segment time_var calculations. + // NOTE: If maximum_speed*time_var value is too low, round-off can cause mm_var to not change. To + // prevent this, simply enforce a minimum speed threshold in the planner. + mm_var = mm_remaining - prep.maximum_speed * time_var; + if (mm_var < prep.decelerate_after) { // End of cruise. + // Cruise-deceleration junction or end of block. + time_var = (mm_remaining - prep.decelerate_after) / prep.maximum_speed; + mm_remaining = prep.decelerate_after; // NOTE: 0.0 at EOB + prep.ramp_type = RAMP_DECEL; + } else // Cruising only. + mm_remaining = mm_var; + break; + default: // case RAMP_DECEL: + // NOTE: mm_var used as a misc worker variable to prevent errors when near zero speed. + speed_var = pl_block->acceleration * time_var; // Used as delta speed (mm/min) + if (prep.current_speed > speed_var) { // Check if at or below zero speed. + // Compute distance from end of segment to end of block. + mm_var = mm_remaining - time_var * (prep.current_speed - 0.5 * speed_var); // (mm) + if (mm_var > prep.mm_complete) { // Typical case. In deceleration ramp. + mm_remaining = mm_var; + prep.current_speed -= speed_var; + break; // Segment complete. Exit switch-case statement. Continue do-while loop. + } } - } - // Otherwise, at end of block or end of forced-deceleration. - time_var = 2.0 * (mm_remaining - prep.mm_complete) / (prep.current_speed + prep.exit_speed); - mm_remaining = prep.mm_complete; - prep.current_speed = prep.exit_speed; + // Otherwise, at end of block or end of forced-deceleration. + time_var = 2.0 * (mm_remaining - prep.mm_complete) / (prep.current_speed + prep.exit_speed); + mm_remaining = prep.mm_complete; + prep.current_speed = prep.exit_speed; } - dt += time_var; // Add computed ramp time to total segment time. + dt += time_var; // Add computed ramp time to total segment time. if (dt < dt_max) { - time_var = dt_max - dt; // **Incomplete** At ramp junction. + time_var = dt_max - dt; // **Incomplete** At ramp junction. } else { - if (mm_remaining > minimum_mm) { // Check for very slow segments with zero steps. + if (mm_remaining > minimum_mm) { // Check for very slow segments with zero steps. // Increase segment time to ensure at least one step in segment. Override and loop // through distance calculations until minimum_mm or mm_complete. dt_max += DT_SEGMENT; time_var = dt_max - dt; } else { - break; // **Complete** Exit loop. Segment execution time maxed. + break; // **Complete** Exit loop. Segment execution time maxed. } } - } while (mm_remaining > prep.mm_complete); // **Complete** Exit loop. Profile complete. + } while (mm_remaining > prep.mm_complete); // **Complete** Exit loop. Profile complete. /* ----------------------------------------------------------------------------------- Compute spindle speed PWM output for step segment @@ -1053,13 +1046,12 @@ void st_prep_buffer() { prep.current_spindle_rpm = rpm; } else { - sys.spindle_speed = 0.0; + sys.spindle_speed = 0.0; prep.current_spindle_rpm = 0.0; - } bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); } - prep_segment->spindle_rpm = prep.current_spindle_rpm; // Reload segment PWM value + prep_segment->spindle_rpm = prep.current_spindle_rpm; // Reload segment PWM value /* ----------------------------------------------------------------------------------- Compute segment step rate, steps to execute, and apply necessary rate corrections. @@ -1071,10 +1063,10 @@ void st_prep_buffer() { Fortunately, this scenario is highly unlikely and unrealistic in CNC machines supported by Grbl (i.e. exceeding 10 meters axis travel at 200 step/mm). */ - float step_dist_remaining = prep.step_per_mm * mm_remaining; // Convert mm_remaining to steps - float n_steps_remaining = ceil(step_dist_remaining); // Round-up current steps remaining - float last_n_steps_remaining = ceil(prep.steps_remaining); // Round-up last steps remaining - prep_segment->n_step = last_n_steps_remaining - n_steps_remaining; // Compute number of steps to execute. + float step_dist_remaining = prep.step_per_mm * mm_remaining; // Convert mm_remaining to steps + float n_steps_remaining = ceil(step_dist_remaining); // Round-up current steps remaining + float last_n_steps_remaining = ceil(prep.steps_remaining); // Round-up last steps remaining + prep_segment->n_step = last_n_steps_remaining - n_steps_remaining; // Compute number of steps to execute. // Bail if we are at the end of a feed hold and don't have a step to execute. if (prep_segment->n_step == 0) { if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) { @@ -1085,7 +1077,7 @@ void st_prep_buffer() { if (!(prep.recalculate_flag & PREP_FLAG_PARKING)) prep.recalculate_flag |= PREP_FLAG_HOLD_PARTIAL_BLOCK; #endif - return; // Segment not generated, but current step data still retained. + return; // Segment not generated, but current step data still retained. } } // Compute segment step rate. Since steps are integers and mm distances traveled are not, @@ -1096,10 +1088,10 @@ void st_prep_buffer() { // adjusts the whole segment rate to keep step output exact. These rate adjustments are // typically very small and do not adversely effect performance, but ensures that Grbl // outputs the exact acceleration and velocity profiles as computed by the planner. - dt += prep.dt_remainder; // Apply previous segment partial step execute time - float inv_rate = dt / (last_n_steps_remaining - step_dist_remaining); // Compute adjusted step rate inverse + dt += prep.dt_remainder; // Apply previous segment partial step execute time + float inv_rate = dt / (last_n_steps_remaining - step_dist_remaining); // Compute adjusted step rate inverse // Compute CPU cycles per step for the prepped segment. - uint32_t cycles = ceil((TICKS_PER_MICROSECOND * 1000000 * 60) * inv_rate); // (cycles/step) + uint32_t cycles = ceil((TICKS_PER_MICROSECOND * 1000000 * 60) * inv_rate); // (cycles/step) #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING // Compute step timing and multi-axis smoothing level. // NOTE: AMASS overdrives the timer with each level, so only one prescalar is required. @@ -1116,23 +1108,23 @@ void st_prep_buffer() { prep_segment->n_step <<= prep_segment->amass_level; } if (cycles < (1UL << 16)) { - prep_segment->cycles_per_tick = cycles; // < 65536 (4.1ms @ 16MHz) + prep_segment->cycles_per_tick = cycles; // < 65536 (4.1ms @ 16MHz) } else { - prep_segment->cycles_per_tick = 0xffff; // Just set the slowest speed possible. + prep_segment->cycles_per_tick = 0xffff; // Just set the slowest speed possible. } #else // Compute step timing and timer prescalar for normal step generation. - if (cycles < (1UL << 16)) { // < 65536 (4.1ms @ 16MHz) - prep_segment->prescaler = 1; // prescaler: 0 + if (cycles < (1UL << 16)) { // < 65536 (4.1ms @ 16MHz) + prep_segment->prescaler = 1; // prescaler: 0 prep_segment->cycles_per_tick = cycles; - } else if (cycles < (1UL << 19)) { // < 524288 (32.8ms@16MHz) - prep_segment->prescaler = 2; // prescaler: 8 + } else if (cycles < (1UL << 19)) { // < 524288 (32.8ms@16MHz) + prep_segment->prescaler = 2; // prescaler: 8 prep_segment->cycles_per_tick = cycles >> 3; } else { - prep_segment->prescaler = 3; // prescaler: 64 - if (cycles < (1UL << 22)) // < 4194304 (262ms@16MHz) - prep_segment->cycles_per_tick = cycles >> 6; - else // Just set the slowest speed possible. (Around 4 step/sec.) + prep_segment->prescaler = 3; // prescaler: 64 + if (cycles < (1UL << 22)) // < 4194304 (262ms@16MHz) + prep_segment->cycles_per_tick = cycles >> 6; + else // Just set the slowest speed possible. (Around 4 step/sec.) prep_segment->cycles_per_tick = 0xffff; } #endif @@ -1142,12 +1134,12 @@ void st_prep_buffer() { segment_next_head = 0; // Update the appropriate planner and segment data. pl_block->millimeters = mm_remaining; - prep.steps_remaining = n_steps_remaining; - prep.dt_remainder = (n_steps_remaining - step_dist_remaining) * inv_rate; + prep.steps_remaining = n_steps_remaining; + prep.dt_remainder = (n_steps_remaining - step_dist_remaining) * inv_rate; // Check for exit conditions and flag to load next planner block. if (mm_remaining == prep.mm_complete) { // End of planner block or forced-termination. No more distance to be executed. - if (mm_remaining > 0.0) { // At end of forced-termination. + if (mm_remaining > 0.0) { // At end of forced-termination. // Reset prep parameters for resuming and then bail. Allow the stepper ISR to complete // the segment queue, where realtime protocol will set new state upon receiving the // cycle stop flag from the ISR. Prep_segment is blocked until then. @@ -1156,22 +1148,20 @@ void st_prep_buffer() { if (!(prep.recalculate_flag & PREP_FLAG_PARKING)) prep.recalculate_flag |= PREP_FLAG_HOLD_PARTIAL_BLOCK; #endif - return; // Bail! - } else { // End of planner block + return; // Bail! + } else { // End of planner block // The planner block is complete. All steps are set to be executed in the segment buffer. if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) { bit_true(sys.step_control, STEP_CONTROL_END_MOTION); return; } - pl_block = NULL; // Set pointer to indicate check and load next planner block. + pl_block = NULL; // Set pointer to indicate check and load next planner block. plan_discard_current_block(); } } } } - - // Called by realtime status reporting to fetch the current speed being executed. This value // however is not exactly the current speed, but the speed computed in the last step segment // in the segment buffer. It will always be behind by up to the number of segment blocks (-1) @@ -1216,15 +1206,15 @@ void IRAM_ATTR Stepper_Timer_Stop() { #endif } -bool get_stepper_disable() { // returns true if steppers are disabled +bool get_stepper_disable() { // returns true if steppers are disabled bool disabled = false; #ifdef STEPPERS_DISABLE_PIN disabled = digitalRead(STEPPERS_DISABLE_PIN); #else - return false; // thery are never disabled if there is no pin defined + return false; // thery are never disabled if there is no pin defined #endif if (step_enable_invert->get()) { - disabled = !disabled; // Apply pin invert. + disabled = !disabled; // Apply pin invert. } return disabled; } diff --git a/Grbl_Esp32/stepper.h b/Grbl_Esp32/stepper.h index 95a483b3..86b5606a 100644 --- a/Grbl_Esp32/stepper.h +++ b/Grbl_Esp32/stepper.h @@ -25,16 +25,14 @@ */ #ifndef SEGMENT_BUFFER_SIZE - #define SEGMENT_BUFFER_SIZE 6 +# define SEGMENT_BUFFER_SIZE 6 #endif - - #include "grbl.h" #include "config.h" // Some useful constants. -#define DT_SEGMENT (1.0/(ACCELERATION_TICKS_PER_SECOND*60.0)) // min/segment +#define DT_SEGMENT (1.0 / (ACCELERATION_TICKS_PER_SECOND * 60.0)) // min/segment #define REQ_MM_INCREMENT_SCALAR 1.25 #define RAMP_ACCEL 0 #define RAMP_CRUISE 1 @@ -59,21 +57,21 @@ #define MAX_AMASS_LEVEL 3 // AMASS_LEVEL0: Normal operation. No AMASS. No upper cutoff frequency. Starts at LEVEL1 cutoff frequency. // Note ESP32 use F_STEPPER_TIMER rather than the AVR F_CPU -#define AMASS_LEVEL1 (F_STEPPER_TIMER/8000) // Over-drives ISR (x2). Defined as F_CPU/(Cutoff frequency in Hz) -#define AMASS_LEVEL2 (F_STEPPER_TIMER/4000) // Over-drives ISR (x4) -#define AMASS_LEVEL3 (F_STEPPER_TIMER/2000) // Over-drives ISR (x8) +#define AMASS_LEVEL1 (F_STEPPER_TIMER / 8000) // Over-drives ISR (x2). Defined as F_CPU/(Cutoff frequency in Hz) +#define AMASS_LEVEL2 (F_STEPPER_TIMER / 4000) // Over-drives ISR (x4) +#define AMASS_LEVEL3 (F_STEPPER_TIMER / 2000) // Over-drives ISR (x8) #if MAX_AMASS_LEVEL <= 0 - error "AMASS must have 1 or more levels to operate correctly." +error "AMASS must have 1 or more levels to operate correctly." #endif //#endif #define STEP_TIMER_GROUP TIMER_GROUP_0 #define STEP_TIMER_INDEX TIMER_0 -// esp32 work around for diable in main loop -extern uint64_t stepper_idle_counter; -extern bool stepper_idle; + // esp32 work around for diable in main loop + extern uint64_t stepper_idle_counter; +extern bool stepper_idle; extern uint8_t ganged_mode; @@ -111,7 +109,7 @@ void st_update_plan_block_parameters(); float st_get_realtime_rate(); // disable (or enable) steppers via STEPPERS_DISABLE_PIN -bool get_stepper_disable(); // returns the state of the pin +bool get_stepper_disable(); // returns the state of the pin void set_stepper_pins_on(uint8_t onMask); void set_direction_pins_on(uint8_t onMask); diff --git a/Grbl_Esp32/system.cpp b/Grbl_Esp32/system.cpp index f735cd75..6ba134ef 100644 --- a/Grbl_Esp32/system.cpp +++ b/Grbl_Esp32/system.cpp @@ -21,10 +21,10 @@ #include "grbl.h" #include "config.h" -xQueueHandle control_sw_queue; // used by control switch debouncing -bool debouncing = false; // debouncing in process +xQueueHandle control_sw_queue; // used by control switch debouncing +bool debouncing = false; // debouncing in process -void system_ini() { // Renamed from system_init() due to conflict with esp32 files +void system_ini() { // Renamed from system_init() due to conflict with esp32 files // setup control inputs #ifdef CONTROL_SAFETY_DOOR_PIN @@ -70,7 +70,7 @@ void system_ini() { // Renamed from system_init() due to conflict with esp32 fil "controlCheckTask", 2048, NULL, - 5, // priority + 5, // priority NULL); #endif @@ -81,19 +81,19 @@ void system_ini() { // Renamed from system_init() due to conflict with esp32 fil // Setup USER_DIGITAL_PINs controlled by M62 and M63 #ifdef USER_DIGITAL_PIN_1 pinMode(USER_DIGITAL_PIN_1, OUTPUT); - sys_io_control(bit(1), false); // turn off + sys_io_control(bit(1), false); // turn off #endif #ifdef USER_DIGITAL_PIN_2 pinMode(USER_DIGITAL_PIN_2, OUTPUT); - sys_io_control(bit(2), false); // turn off + sys_io_control(bit(2), false); // turn off #endif #ifdef USER_DIGITAL_PIN_3 pinMode(USER_DIGITAL_PIN_3, OUTPUT); - sys_io_control(bit(3), false); // turn off + sys_io_control(bit(3), false); // turn off #endif #ifdef USER_DIGITAL_PIN_4 pinMode(USER_DIGITAL_PIN_4, OUTPUT); - sys_io_control(bit(4), false); // turn off + sys_io_control(bit(4), false); // turn off #endif } @@ -102,8 +102,8 @@ void system_ini() { // Renamed from system_init() due to conflict with esp32 fil void controlCheckTask(void* pvParameters) { while (true) { int evt; - xQueueReceive(control_sw_queue, &evt, portMAX_DELAY); // block until receive queue - vTaskDelay(CONTROL_SW_DEBOUNCE_PERIOD); // delay a while + xQueueReceive(control_sw_queue, &evt, portMAX_DELAY); // block until receive queue + vTaskDelay(CONTROL_SW_DEBOUNCE_PERIOD); // delay a while uint8_t pin = system_control_get_state(); if (pin) system_exec_control_pin(pin); @@ -116,7 +116,7 @@ void IRAM_ATTR isr_control_inputs() { #ifdef ENABLE_CONTROL_SW_DEBOUNCE // we will start a task that will recheck the switches after a small delay int evt; - if (!debouncing) { // prevent resending until debounce is done + if (!debouncing) { // prevent resending until debounce is done debouncing = true; xQueueSendFromISR(control_sw_queue, &evt, NULL); } @@ -131,7 +131,7 @@ uint8_t system_check_safety_door_ajar() { #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN return (system_control_get_state() & CONTROL_PIN_INDEX_SAFETY_DOOR); #else - return (false); // Input pin not enabled, so just return that it's closed. + return (false); // Input pin not enabled, so just return that it's closed. #endif } @@ -192,7 +192,6 @@ void system_clear_exec_accessory_overrides() { //SREG = sreg; } - void system_flag_wco_change() { #ifdef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE protocol_buffer_synchronize(); @@ -200,7 +199,6 @@ void system_flag_wco_change() { sys.report_wco_counter = 0; } - // Returns machine position of axis 'idx'. Must be sent a 'step' array. // NOTE: If motor steps and machine position are not in the same coordinate frame, this function // serves as a central place to compute the transformation. @@ -236,16 +234,20 @@ uint8_t system_check_travel_limits(float* target) { uint8_t mask = homing_dir_mask->get(); // When homing forced set origin is enabled, soft limits checks need to account for directionality. if (bit_istrue(mask, bit(idx))) { - if (target[idx] < 0 || target[idx] > travel) return (true); + if (target[idx] < 0 || target[idx] > travel) + return (true); } else { - if (target[idx] > 0 || target[idx] < -travel) return (true); + if (target[idx] > 0 || target[idx] < -travel) + return (true); } #else -#ifdef HOMING_FORCE_POSITIVE_SPACE - if (target[idx] < 0 || target[idx] > travel) return (true); -#else - if (target[idx] > 0 || target[idx] < -travel) return (true); -#endif +# ifdef HOMING_FORCE_POSITIVE_SPACE + if (target[idx] < 0 || target[idx] > travel) + return (true); +# else + if (target[idx] > 0 || target[idx] < -travel) + return (true); +# endif #endif } return (false); @@ -255,40 +257,48 @@ uint8_t system_check_travel_limits(float* target) { // triggered is 1 and not triggered is 0. Invert mask is applied. Bitfield organization is // defined by the CONTROL_PIN_INDEX in the header file. uint8_t system_control_get_state() { - uint8_t defined_pin_mask = 0; // a mask of defined pins - uint8_t control_state = 0; - + uint8_t defined_pin_mask = 0; // a mask of defined pins + uint8_t control_state = 0; + #ifdef CONTROL_SAFETY_DOOR_PIN defined_pin_mask |= CONTROL_PIN_INDEX_SAFETY_DOOR; - if (digitalRead(CONTROL_SAFETY_DOOR_PIN)) control_state |= CONTROL_PIN_INDEX_SAFETY_DOOR; + if (digitalRead(CONTROL_SAFETY_DOOR_PIN)) + control_state |= CONTROL_PIN_INDEX_SAFETY_DOOR; #endif #ifdef CONTROL_RESET_PIN defined_pin_mask |= CONTROL_PIN_INDEX_RESET; - if (digitalRead(CONTROL_RESET_PIN)) control_state |= CONTROL_PIN_INDEX_RESET; + if (digitalRead(CONTROL_RESET_PIN)) + control_state |= CONTROL_PIN_INDEX_RESET; #endif #ifdef CONTROL_FEED_HOLD_PIN defined_pin_mask |= CONTROL_PIN_INDEX_FEED_HOLD; - if (digitalRead(CONTROL_FEED_HOLD_PIN)) control_state |= CONTROL_PIN_INDEX_FEED_HOLD; + if (digitalRead(CONTROL_FEED_HOLD_PIN)) + control_state |= CONTROL_PIN_INDEX_FEED_HOLD; #endif #ifdef CONTROL_CYCLE_START_PIN defined_pin_mask |= CONTROL_PIN_INDEX_CYCLE_START; - if (digitalRead(CONTROL_CYCLE_START_PIN)) control_state |= CONTROL_PIN_INDEX_CYCLE_START; + if (digitalRead(CONTROL_CYCLE_START_PIN)) + control_state |= CONTROL_PIN_INDEX_CYCLE_START; #endif #ifdef MACRO_BUTTON_0_PIN defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_0; - if (digitalRead(MACRO_BUTTON_0_PIN)) control_state |= CONTROL_PIN_INDEX_MACRO_0; + if (digitalRead(MACRO_BUTTON_0_PIN)) + control_state |= CONTROL_PIN_INDEX_MACRO_0; #endif #ifdef MACRO_BUTTON_1_PIN defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_1; - if (digitalRead(MACRO_BUTTON_1_PIN)) control_state |= CONTROL_PIN_INDEX_MACRO_1; + if (digitalRead(MACRO_BUTTON_1_PIN)) + control_state |= CONTROL_PIN_INDEX_MACRO_1; #endif #ifdef MACRO_BUTTON_2_PIN defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_2; - if (digitalRead(MACRO_BUTTON_2_PIN)) control_state |= CONTROL_PIN_INDEX_MACRO_2; + if (digitalRead(MACRO_BUTTON_2_PIN)) + control_state |= CONTROL_PIN_INDEX_MACRO_2; #endif #ifdef MACRO_BUTTON_3_PIN defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_3; - if (digitalRead(MACRO_BUTTON_3_PIN)) control_state |= CONTROL_PIN_INDEX_MACRO_3; + if (digitalRead(MACRO_BUTTON_3_PIN)) + control_state |= CONTROL_PIN_INDEX_MACRO_3; #endif #ifdef INVERT_CONTROL_PIN_MASK control_state ^= (INVERT_CONTROL_PIN_MASK & defined_pin_mask); @@ -309,22 +319,22 @@ void system_exec_control_pin(uint8_t pin) { bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR); #ifdef MACRO_BUTTON_0_PIN else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_0)) { - user_defined_macro(CONTROL_PIN_INDEX_MACRO_0); // function must be implemented by user + user_defined_macro(CONTROL_PIN_INDEX_MACRO_0); // function must be implemented by user } #endif #ifdef MACRO_BUTTON_1_PIN else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_1)) { - user_defined_macro(CONTROL_PIN_INDEX_MACRO_1); // function must be implemented by user + user_defined_macro(CONTROL_PIN_INDEX_MACRO_1); // function must be implemented by user } #endif #ifdef MACRO_BUTTON_2_PIN else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_2)) { - user_defined_macro(CONTROL_PIN_INDEX_MACRO_2); // function must be implemented by user + user_defined_macro(CONTROL_PIN_INDEX_MACRO_2); // function must be implemented by user } #endif #ifdef MACRO_BUTTON_3_PIN else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_3)) { - user_defined_macro(CONTROL_PIN_INDEX_MACRO_3); // function must be implemented by user + user_defined_macro(CONTROL_PIN_INDEX_MACRO_3); // function must be implemented by user } #endif } @@ -374,12 +384,11 @@ void fast_sys_io_control(uint8_t io_num_mask, bool turnOn) { #endif } - // Call this function to get an RMT channel number // returns -1 for error int8_t sys_get_next_RMT_chan_num() { - static uint8_t next_RMT_chan_num = 0; // channels 0-7 are valid - if (next_RMT_chan_num < 8) // 7 is the max PWM channel number + static uint8_t next_RMT_chan_num = 0; // channels 0-7 are valid + if (next_RMT_chan_num < 8) // 7 is the max PWM channel number return next_RMT_chan_num++; else { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_ERROR, "Error: out of RMT channels"); @@ -387,7 +396,6 @@ int8_t sys_get_next_RMT_chan_num() { } } - /* This returns an unused pwm channel. The 8 channels share 4 timers, so pairs 0,1 & 2,3 , etc @@ -398,8 +406,8 @@ int8_t sys_get_next_RMT_chan_num() { TODO: Make this more robust. */ int8_t sys_get_next_PWM_chan_num() { - static uint8_t next_PWM_chan_num = 2; // start at 2 to avoid spindle - if (next_PWM_chan_num < 8) // 7 is the max PWM channel number + static uint8_t next_PWM_chan_num = 2; // start at 2 to avoid spindle + if (next_PWM_chan_num < 8) // 7 is the max PWM channel number return next_PWM_chan_num++; else { grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_ERROR, "Error: out of PWM channels"); diff --git a/Grbl_Esp32/system.h b/Grbl_Esp32/system.h index b91a8fce..4211c51c 100644 --- a/Grbl_Esp32/system.h +++ b/Grbl_Esp32/system.h @@ -40,7 +40,7 @@ typedef struct { uint8_t report_ovr_counter; // Tracks when to add override data to status reports. uint8_t report_wco_counter; // Tracks when to add work coordinate offset data to status reports. #ifdef ENABLE_PARKING_OVERRIDE_CONTROL - uint8_t override_ctrl; // Tracks override control states. + uint8_t override_ctrl; // Tracks override control states. #endif uint32_t spindle_speed; @@ -48,98 +48,95 @@ typedef struct { } system_t; extern system_t sys; - - - // Define system executor bit map. Used internally by realtime protocol as realtime command flags, // which notifies the main program to execute the specified realtime command asynchronously. // NOTE: The system executor uses an unsigned 8-bit volatile variable (8 flag limit.) The default // flags are always false, so the realtime protocol only needs to check for a non-zero value to // know when there is a realtime command to execute. -#define EXEC_STATUS_REPORT bit(0) // bitmask 00000001 -#define EXEC_CYCLE_START bit(1) // bitmask 00000010 -#define EXEC_CYCLE_STOP bit(2) // bitmask 00000100 -#define EXEC_FEED_HOLD bit(3) // bitmask 00001000 -#define EXEC_RESET bit(4) // bitmask 00010000 -#define EXEC_SAFETY_DOOR bit(5) // bitmask 00100000 -#define EXEC_MOTION_CANCEL bit(6) // bitmask 01000000 -#define EXEC_SLEEP bit(7) // bitmask 10000000 +#define EXEC_STATUS_REPORT bit(0) // bitmask 00000001 +#define EXEC_CYCLE_START bit(1) // bitmask 00000010 +#define EXEC_CYCLE_STOP bit(2) // bitmask 00000100 +#define EXEC_FEED_HOLD bit(3) // bitmask 00001000 +#define EXEC_RESET bit(4) // bitmask 00010000 +#define EXEC_SAFETY_DOOR bit(5) // bitmask 00100000 +#define EXEC_MOTION_CANCEL bit(6) // bitmask 01000000 +#define EXEC_SLEEP bit(7) // bitmask 10000000 // Alarm executor codes. Valid values (1-255). Zero is reserved. -#define EXEC_ALARM_HARD_LIMIT 1 -#define EXEC_ALARM_SOFT_LIMIT 2 -#define EXEC_ALARM_ABORT_CYCLE 3 -#define EXEC_ALARM_PROBE_FAIL_INITIAL 4 -#define EXEC_ALARM_PROBE_FAIL_CONTACT 5 -#define EXEC_ALARM_HOMING_FAIL_RESET 6 -#define EXEC_ALARM_HOMING_FAIL_DOOR 7 -#define EXEC_ALARM_HOMING_FAIL_PULLOFF 8 +#define EXEC_ALARM_HARD_LIMIT 1 +#define EXEC_ALARM_SOFT_LIMIT 2 +#define EXEC_ALARM_ABORT_CYCLE 3 +#define EXEC_ALARM_PROBE_FAIL_INITIAL 4 +#define EXEC_ALARM_PROBE_FAIL_CONTACT 5 +#define EXEC_ALARM_HOMING_FAIL_RESET 6 +#define EXEC_ALARM_HOMING_FAIL_DOOR 7 +#define EXEC_ALARM_HOMING_FAIL_PULLOFF 8 #define EXEC_ALARM_HOMING_FAIL_APPROACH 9 -#define EXEC_ALARM_SPINDLE_CONTROL 10 +#define EXEC_ALARM_SPINDLE_CONTROL 10 // Override bit maps. Realtime bitflags to control feed, rapid, spindle, and coolant overrides. // Spindle/coolant and feed/rapids are separated into two controlling flag variables. -#define EXEC_FEED_OVR_RESET bit(0) -#define EXEC_FEED_OVR_COARSE_PLUS bit(1) -#define EXEC_FEED_OVR_COARSE_MINUS bit(2) -#define EXEC_FEED_OVR_FINE_PLUS bit(3) -#define EXEC_FEED_OVR_FINE_MINUS bit(4) -#define EXEC_RAPID_OVR_RESET bit(5) -#define EXEC_RAPID_OVR_MEDIUM bit(6) -#define EXEC_RAPID_OVR_LOW bit(7) +#define EXEC_FEED_OVR_RESET bit(0) +#define EXEC_FEED_OVR_COARSE_PLUS bit(1) +#define EXEC_FEED_OVR_COARSE_MINUS bit(2) +#define EXEC_FEED_OVR_FINE_PLUS bit(3) +#define EXEC_FEED_OVR_FINE_MINUS bit(4) +#define EXEC_RAPID_OVR_RESET bit(5) +#define EXEC_RAPID_OVR_MEDIUM bit(6) +#define EXEC_RAPID_OVR_LOW bit(7) // #define EXEC_RAPID_OVR_EXTRA_LOW bit(*) // *NOT SUPPORTED* -#define EXEC_SPINDLE_OVR_RESET bit(0) -#define EXEC_SPINDLE_OVR_COARSE_PLUS bit(1) -#define EXEC_SPINDLE_OVR_COARSE_MINUS bit(2) -#define EXEC_SPINDLE_OVR_FINE_PLUS bit(3) -#define EXEC_SPINDLE_OVR_FINE_MINUS bit(4) -#define EXEC_SPINDLE_OVR_STOP bit(5) -#define EXEC_COOLANT_FLOOD_OVR_TOGGLE bit(6) -#define EXEC_COOLANT_MIST_OVR_TOGGLE bit(7) +#define EXEC_SPINDLE_OVR_RESET bit(0) +#define EXEC_SPINDLE_OVR_COARSE_PLUS bit(1) +#define EXEC_SPINDLE_OVR_COARSE_MINUS bit(2) +#define EXEC_SPINDLE_OVR_FINE_PLUS bit(3) +#define EXEC_SPINDLE_OVR_FINE_MINUS bit(4) +#define EXEC_SPINDLE_OVR_STOP bit(5) +#define EXEC_COOLANT_FLOOD_OVR_TOGGLE bit(6) +#define EXEC_COOLANT_MIST_OVR_TOGGLE bit(7) // Define system state bit map. The state variable primarily tracks the individual functions // of Grbl to manage each without overlapping. It is also used as a messaging flag for // critical events. -#define STATE_IDLE 0 // Must be zero. No flags. -#define STATE_ALARM bit(0) // In alarm state. Locks out all g-code processes. Allows settings access. -#define STATE_CHECK_MODE bit(1) // G-code check mode. Locks out planner and motion only. -#define STATE_HOMING bit(2) // Performing homing cycle -#define STATE_CYCLE bit(3) // Cycle is running or motions are being executed. -#define STATE_HOLD bit(4) // Active feed hold -#define STATE_JOG bit(5) // Jogging mode. -#define STATE_SAFETY_DOOR bit(6) // Safety door is ajar. Feed holds and de-energizes system. -#define STATE_SLEEP bit(7) // Sleep state. +#define STATE_IDLE 0 // Must be zero. No flags. +#define STATE_ALARM bit(0) // In alarm state. Locks out all g-code processes. Allows settings access. +#define STATE_CHECK_MODE bit(1) // G-code check mode. Locks out planner and motion only. +#define STATE_HOMING bit(2) // Performing homing cycle +#define STATE_CYCLE bit(3) // Cycle is running or motions are being executed. +#define STATE_HOLD bit(4) // Active feed hold +#define STATE_JOG bit(5) // Jogging mode. +#define STATE_SAFETY_DOOR bit(6) // Safety door is ajar. Feed holds and de-energizes system. +#define STATE_SLEEP bit(7) // Sleep state. // Define system suspend flags. Used in various ways to manage suspend states and procedures. -#define SUSPEND_DISABLE 0 // Must be zero. -#define SUSPEND_HOLD_COMPLETE bit(0) // Indicates initial feed hold is complete. -#define SUSPEND_RESTART_RETRACT bit(1) // Flag to indicate a retract from a restore parking motion. -#define SUSPEND_RETRACT_COMPLETE bit(2) // (Safety door only) Indicates retraction and de-energizing is complete. -#define SUSPEND_INITIATE_RESTORE bit(3) // (Safety door only) Flag to initiate resume procedures from a cycle start. -#define SUSPEND_RESTORE_COMPLETE bit(4) // (Safety door only) Indicates ready to resume normal operation. -#define SUSPEND_SAFETY_DOOR_AJAR bit(5) // Tracks safety door state for resuming. -#define SUSPEND_MOTION_CANCEL bit(6) // Indicates a canceled resume motion. Currently used by probing routine. -#define SUSPEND_JOG_CANCEL bit(7) // Indicates a jog cancel in process and to reset buffers when complete. +#define SUSPEND_DISABLE 0 // Must be zero. +#define SUSPEND_HOLD_COMPLETE bit(0) // Indicates initial feed hold is complete. +#define SUSPEND_RESTART_RETRACT bit(1) // Flag to indicate a retract from a restore parking motion. +#define SUSPEND_RETRACT_COMPLETE bit(2) // (Safety door only) Indicates retraction and de-energizing is complete. +#define SUSPEND_INITIATE_RESTORE bit(3) // (Safety door only) Flag to initiate resume procedures from a cycle start. +#define SUSPEND_RESTORE_COMPLETE bit(4) // (Safety door only) Indicates ready to resume normal operation. +#define SUSPEND_SAFETY_DOOR_AJAR bit(5) // Tracks safety door state for resuming. +#define SUSPEND_MOTION_CANCEL bit(6) // Indicates a canceled resume motion. Currently used by probing routine. +#define SUSPEND_JOG_CANCEL bit(7) // Indicates a jog cancel in process and to reset buffers when complete. // Define step segment generator state flags. -#define STEP_CONTROL_NORMAL_OP 0 // Must be zero. -#define STEP_CONTROL_END_MOTION bit(0) -#define STEP_CONTROL_EXECUTE_HOLD bit(1) -#define STEP_CONTROL_EXECUTE_SYS_MOTION bit(2) -#define STEP_CONTROL_UPDATE_SPINDLE_RPM bit(3) +#define STEP_CONTROL_NORMAL_OP 0 // Must be zero. +#define STEP_CONTROL_END_MOTION bit(0) +#define STEP_CONTROL_EXECUTE_HOLD bit(1) +#define STEP_CONTROL_EXECUTE_SYS_MOTION bit(2) +#define STEP_CONTROL_UPDATE_SPINDLE_RPM bit(3) // Define control pin index for Grbl internal use. Pin maps may change, but these values don't. //#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN #define N_CONTROL_PIN 4 -#define CONTROL_PIN_INDEX_SAFETY_DOOR bit(0) -#define CONTROL_PIN_INDEX_RESET bit(1) -#define CONTROL_PIN_INDEX_FEED_HOLD bit(2) -#define CONTROL_PIN_INDEX_CYCLE_START bit(3) -#define CONTROL_PIN_INDEX_MACRO_0 bit(4) -#define CONTROL_PIN_INDEX_MACRO_1 bit(5) -#define CONTROL_PIN_INDEX_MACRO_2 bit(6) -#define CONTROL_PIN_INDEX_MACRO_3 bit(7) +#define CONTROL_PIN_INDEX_SAFETY_DOOR bit(0) +#define CONTROL_PIN_INDEX_RESET bit(1) +#define CONTROL_PIN_INDEX_FEED_HOLD bit(2) +#define CONTROL_PIN_INDEX_CYCLE_START bit(3) +#define CONTROL_PIN_INDEX_MACRO_0 bit(4) +#define CONTROL_PIN_INDEX_MACRO_1 bit(5) +#define CONTROL_PIN_INDEX_MACRO_2 bit(6) +#define CONTROL_PIN_INDEX_MACRO_3 bit(7) //#else //#define N_CONTROL_PIN 3 //#define CONTROL_PIN_INDEX_RESET bit(0) @@ -148,29 +145,28 @@ extern system_t sys; //#endif // Define spindle stop override control states. -#define SPINDLE_STOP_OVR_DISABLED 0 // Must be zero. -#define SPINDLE_STOP_OVR_ENABLED bit(0) -#define SPINDLE_STOP_OVR_INITIATE bit(1) -#define SPINDLE_STOP_OVR_RESTORE bit(2) -#define SPINDLE_STOP_OVR_RESTORE_CYCLE bit(3) +#define SPINDLE_STOP_OVR_DISABLED 0 // Must be zero. +#define SPINDLE_STOP_OVR_ENABLED bit(0) +#define SPINDLE_STOP_OVR_INITIATE bit(1) +#define SPINDLE_STOP_OVR_RESTORE bit(2) +#define SPINDLE_STOP_OVR_RESTORE_CYCLE bit(3) // NOTE: These position variables may need to be declared as volatiles, if problems arise. -extern int32_t sys_position[N_AXIS]; // Real-time machine (aka home) position vector in steps. -extern int32_t sys_probe_position[N_AXIS]; // Last probe position in machine coordinates and steps. +extern int32_t sys_position[N_AXIS]; // Real-time machine (aka home) position vector in steps. +extern int32_t sys_probe_position[N_AXIS]; // Last probe position in machine coordinates and steps. -extern volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR. -extern volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks. -extern volatile uint8_t sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms. -extern volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides. -extern volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides. +extern volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR. +extern volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks. +extern volatile uint8_t sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms. +extern volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides. +extern volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides. #ifdef DEBUG - #define EXEC_DEBUG_REPORT bit(0) - extern volatile uint8_t sys_rt_exec_debug; +# define EXEC_DEBUG_REPORT bit(0) +extern volatile uint8_t sys_rt_exec_debug; #endif - -void system_ini(); // Renamed from system_init() due to conflict with esp32 files +void system_ini(); // Renamed from system_init() due to conflict with esp32 files // Returns bitfield of control pin states, organized by CONTROL_PIN_INDEX. (1=triggered, 0=not triggered). uint8_t system_control_get_state(); @@ -191,12 +187,12 @@ void system_clear_exec_motion_overrides(); void system_clear_exec_accessory_overrides(); // Execute the startup script lines stored in EEPROM upon initialization -void system_execute_startup(char* line); +void system_execute_startup(char* line); uint8_t execute_line(char* line, uint8_t client, auth_t auth_level); uint8_t system_execute_line(char* line, ESPResponseStream*, auth_t); uint8_t system_execute_line(char* line, uint8_t client, auth_t); -uint8_t do_command_or_setting(const char *key, char *value, auth_t auth_level, ESPResponseStream*); -void system_flag_wco_change(); +uint8_t do_command_or_setting(const char* key, char* value, auth_t auth_level, ESPResponseStream*); +void system_flag_wco_change(); // Returns machine position of axis 'idx'. Must be sent a 'step' array. float system_convert_axis_steps_to_mpos(int32_t* steps, uint8_t idx); @@ -217,7 +213,6 @@ void system_set_exec_accessory_override_flag(uint8_t mask); void system_clear_exec_motion_overrides(); void system_clear_exec_accessory_overrides(); - int32_t system_convert_corexy_to_x_axis_steps(int32_t* steps); int32_t system_convert_corexy_to_y_axis_steps(int32_t* steps); diff --git a/Grbl_Esp32/telnet_server.cpp b/Grbl_Esp32/telnet_server.cpp index 13d36667..16f7f904 100644 --- a/Grbl_Esp32/telnet_server.cpp +++ b/Grbl_Esp32/telnet_server.cpp @@ -18,30 +18,28 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef ARDUINO_ARCH_ESP32 - #include "grbl.h" -#if defined (ENABLE_WIFI) && defined (ENABLE_TELNET) +#if defined(ENABLE_WIFI) && defined(ENABLE_TELNET) -#include "wifiservices.h" +# include "wifiservices.h" -#include "telnet_server.h" -#include "wificonfig.h" -#include +# include "telnet_server.h" +# include "wificonfig.h" +# include Telnet_Server telnet_server; -bool Telnet_Server::_setupdone = false; -uint16_t Telnet_Server::_port = 0; -WiFiServer* Telnet_Server::_telnetserver = NULL; -WiFiClient Telnet_Server::_telnetClients[MAX_TLNT_CLIENTS]; -#ifdef ENABLE_TELNET_WELCOME_MSG - IPAddress Telnet_Server::_telnetClientsIP[MAX_TLNT_CLIENTS]; -#endif +bool Telnet_Server::_setupdone = false; +uint16_t Telnet_Server::_port = 0; +WiFiServer* Telnet_Server::_telnetserver = NULL; +WiFiClient Telnet_Server::_telnetClients[MAX_TLNT_CLIENTS]; +# ifdef ENABLE_TELNET_WELCOME_MSG +IPAddress Telnet_Server::_telnetClientsIP[MAX_TLNT_CLIENTS]; +# endif Telnet_Server::Telnet_Server() { _RXbufferSize = 0; - _RXbufferpos = 0; + _RXbufferpos = 0; } Telnet_Server::~Telnet_Server() { end(); @@ -51,7 +49,8 @@ bool Telnet_Server::begin() { bool no_error = true; end(); _RXbufferSize = 0; - _RXbufferpos = 0;; + _RXbufferpos = 0; + ; if (telnet_enable->get() == 0) { return false; } @@ -69,9 +68,9 @@ bool Telnet_Server::begin() { } void Telnet_Server::end() { - _setupdone = false; + _setupdone = false; _RXbufferSize = 0; - _RXbufferpos = 0; + _RXbufferpos = 0; if (_telnetserver) { delete _telnetserver; _telnetserver = NULL; @@ -85,10 +84,11 @@ void Telnet_Server::clearClients() { for (i = 0; i < MAX_TLNT_CLIENTS; i++) { //find free/disconnected spot if (!_telnetClients[i] || !_telnetClients[i].connected()) { -#ifdef ENABLE_TELNET_WELCOME_MSG +# ifdef ENABLE_TELNET_WELCOME_MSG _telnetClientsIP[i] = IPAddress(0, 0, 0, 0); -#endif - if (_telnetClients[i]) _telnetClients[i].stop(); +# endif + if (_telnetClients[i]) + _telnetClients[i].stop(); _telnetClients[i] = _telnetserver->available(); break; } @@ -129,19 +129,21 @@ void Telnet_Server::handle() { //uint8_t c; for (uint8_t i = 0; i < MAX_TLNT_CLIENTS; i++) { if (_telnetClients[i] && _telnetClients[i].connected()) { -#ifdef ENABLE_TELNET_WELCOME_MSG +# ifdef ENABLE_TELNET_WELCOME_MSG if (_telnetClientsIP[i] != _telnetClients[i].remoteIP()) { report_init_message(CLIENT_TELNET); _telnetClientsIP[i] = _telnetClients[i].remoteIP(); } -#endif +# endif if (_telnetClients[i].available()) { uint8_t buf[1024]; COMMANDS::wait(0); - int readlen = _telnetClients[i].available(); + int readlen = _telnetClients[i].available(); int writelen = TELNETRXBUFFERSIZE - available(); - if (readlen > 1024) readlen = 1024; - if (readlen > writelen) readlen = writelen; + if (readlen > 1024) + readlen = 1024; + if (readlen > writelen) + readlen = writelen; if (readlen > 0) { _telnetClients[i].read(buf, readlen); push(buf, readlen); @@ -150,9 +152,9 @@ void Telnet_Server::handle() { } } else { if (_telnetClients[i]) { -#ifdef ENABLE_TELNET_WELCOME_MSG +# ifdef ENABLE_TELNET_WELCOME_MSG _telnetClientsIP[i] = IPAddress(0, 0, 0, 0); -#endif +# endif _telnetClients[i].stop(); } } @@ -161,8 +163,10 @@ void Telnet_Server::handle() { } int Telnet_Server::peek(void) { - if (_RXbufferSize > 0)return _RXbuffer[_RXbufferpos]; - else return -1; + if (_RXbufferSize > 0) + return _RXbuffer[_RXbufferpos]; + else + return -1; } int Telnet_Server::available() { @@ -177,8 +181,10 @@ bool Telnet_Server::push(uint8_t data) { log_i("[TELNET]push %c", data); if ((1 + _RXbufferSize) <= TELNETRXBUFFERSIZE) { int current = _RXbufferpos + _RXbufferSize; - if (current > TELNETRXBUFFERSIZE) current = current - TELNETRXBUFFERSIZE; - if (current > (TELNETRXBUFFERSIZE - 1)) current = 0; + if (current > TELNETRXBUFFERSIZE) + current = current - TELNETRXBUFFERSIZE; + if (current > (TELNETRXBUFFERSIZE - 1)) + current = 0; _RXbuffer[current] = data; _RXbufferSize++; log_i("[TELNET]buffer size %d", _RXbufferSize); @@ -190,13 +196,15 @@ bool Telnet_Server::push(uint8_t data) { bool Telnet_Server::push(const uint8_t* data, int data_size) { if ((data_size + _RXbufferSize) <= TELNETRXBUFFERSIZE) { int data_processed = 0; - int current = _RXbufferpos + _RXbufferSize; - if (current > TELNETRXBUFFERSIZE) current = current - TELNETRXBUFFERSIZE; + int current = _RXbufferpos + _RXbufferSize; + if (current > TELNETRXBUFFERSIZE) + current = current - TELNETRXBUFFERSIZE; for (int i = 0; i < data_size; i++) { - if (current > (TELNETRXBUFFERSIZE - 1)) current = 0; + if (current > (TELNETRXBUFFERSIZE - 1)) + current = 0; if (char(data[i]) != '\r') { _RXbuffer[current] = data[i]; - current ++; + current++; data_processed++; } COMMANDS::wait(0); @@ -213,12 +221,12 @@ int Telnet_Server::read(void) { int v = _RXbuffer[_RXbufferpos]; //log_d("[TELNET]read %c",char(v)); _RXbufferpos++; - if (_RXbufferpos > (TELNETRXBUFFERSIZE - 1))_RXbufferpos = 0; + if (_RXbufferpos > (TELNETRXBUFFERSIZE - 1)) + _RXbufferpos = 0; _RXbufferSize--; return v; - } else return -1; + } else + return -1; } -#endif // Enable TELNET && ENABLE_WIFI - -#endif // ARDUINO_ARCH_ESP32 +#endif // Enable TELNET && ENABLE_WIFI diff --git a/Grbl_Esp32/telnet_server.h b/Grbl_Esp32/telnet_server.h index 200674ed..91aa58df 100644 --- a/Grbl_Esp32/telnet_server.h +++ b/Grbl_Esp32/telnet_server.h @@ -31,33 +31,34 @@ class WiFiClient; #define FLUSHTIMEOUT 500 class Telnet_Server { - public: +public: Telnet_Server(); ~Telnet_Server(); - bool begin(); - void end(); - void handle(); - size_t write(const uint8_t* buffer, size_t size); - int read(void); - int peek(void); - int available(); - int get_rx_buffer_available(); - bool push(uint8_t data); - bool push(const uint8_t* data, int datasize); - static uint16_t port() {return _port;} - private: - static bool _setupdone; + bool begin(); + void end(); + void handle(); + size_t write(const uint8_t* buffer, size_t size); + int read(void); + int peek(void); + int available(); + int get_rx_buffer_available(); + bool push(uint8_t data); + bool push(const uint8_t* data, int datasize); + static uint16_t port() { return _port; } + +private: + static bool _setupdone; static WiFiServer* _telnetserver; - static WiFiClient _telnetClients[MAX_TLNT_CLIENTS]; + static WiFiClient _telnetClients[MAX_TLNT_CLIENTS]; #ifdef ENABLE_TELNET_WELCOME_MSG static IPAddress _telnetClientsIP[MAX_TLNT_CLIENTS]; #endif static uint16_t _port; - void clearClients(); - uint32_t _lastflush; - uint8_t _RXbuffer[TELNETRXBUFFERSIZE]; - uint16_t _RXbufferSize; - uint16_t _RXbufferpos; + void clearClients(); + uint32_t _lastflush; + uint8_t _RXbuffer[TELNETRXBUFFERSIZE]; + uint16_t _RXbufferSize; + uint16_t _RXbufferpos; }; extern Telnet_Server telnet_server; diff --git a/Grbl_Esp32/web_server.cpp b/Grbl_Esp32/web_server.cpp index 18678f6c..cba44b69 100644 --- a/Grbl_Esp32/web_server.cpp +++ b/Grbl_Esp32/web_server.cpp @@ -18,178 +18,181 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef ARDUINO_ARCH_ESP32 - #include "grbl.h" -#if defined (ENABLE_WIFI) && defined (ENABLE_HTTP) +#if defined(ENABLE_WIFI) && defined(ENABLE_HTTP) -#include "wifiservices.h" +# include "wifiservices.h" -#include "espresponse.h" -#include "serial2socket.h" -#include "web_server.h" -#include -#include -#include -#include -#ifdef ENABLE_SD_CARD -#include -#include "grbl_sd.h" -#endif -#include -#include -#include -#include -#include -#ifdef ENABLE_MDNS -#include -#endif -#ifdef ENABLE_SSDP -#include -#endif -#ifdef ENABLE_CAPTIVE_PORTAL -#include +# include "espresponse.h" +# include "serial2socket.h" +# include "web_server.h" +# include +# include +# include +# include +# ifdef ENABLE_SD_CARD +# include +# include "grbl_sd.h" +# endif +# include +# include +# include +# include +# include +# ifdef ENABLE_MDNS +# include +# endif +# ifdef ENABLE_SSDP +# include +# endif +# ifdef ENABLE_CAPTIVE_PORTAL +# include const byte DNS_PORT = 53; -DNSServer dnsServer; -#endif -#include +DNSServer dnsServer; +# endif +# include //embedded response file if no files on SPIFFS -#include "nofile.h" +# include "nofile.h" //Upload status typedef enum { - UPLOAD_STATUS_NONE = 0, - UPLOAD_STATUS_FAILED = 1, - UPLOAD_STATUS_CANCELLED = 2, + UPLOAD_STATUS_NONE = 0, + UPLOAD_STATUS_FAILED = 1, + UPLOAD_STATUS_CANCELLED = 2, UPLOAD_STATUS_SUCCESSFUL = 3, - UPLOAD_STATUS_ONGOING = 4 + UPLOAD_STATUS_ONGOING = 4 } upload_status_type; - //Default 404 -const char PAGE_404 [] = "\n\nRedirecting... \n\n\n
Unknown page : $QUERY$- you will be redirected...\n

\nif not redirected, click here\n

\n\n\n\n
\n\n\n\n"; -const char PAGE_CAPTIVE [] = "\n\nCaptive Portal \n\n\n
Captive Portal page : $QUERY$- you will be redirected...\n

\nif not redirected, click here\n

\n\n\n\n
\n\n\n\n"; +const char PAGE_404[] = + "\n\nRedirecting... \n\n\n
Unknown page : $QUERY$- you will be " + "redirected...\n

\nif not redirected, click here\n

\n\n\n\n
\n\n\n\n"; +const char PAGE_CAPTIVE[] = + "\n\nCaptive Portal \n\n\n
Captive Portal page : $QUERY$- you will be " + "redirected...\n

\nif not redirected, click here\n

\n\n\n\n
\n\n\n\n"; -//error codes fo upload -#define ESP_ERROR_AUTHENTICATION 1 -#define ESP_ERROR_FILE_CREATION 2 -#define ESP_ERROR_FILE_WRITE 3 -#define ESP_ERROR_UPLOAD 4 -#define ESP_ERROR_NOT_ENOUGH_SPACE 5 -#define ESP_ERROR_UPLOAD_CANCELLED 6 -#define ESP_ERROR_FILE_CLOSE 7 -#define ESP_ERROR_NO_SD 8 +//error codes fo upload +# define ESP_ERROR_AUTHENTICATION 1 +# define ESP_ERROR_FILE_CREATION 2 +# define ESP_ERROR_FILE_WRITE 3 +# define ESP_ERROR_UPLOAD 4 +# define ESP_ERROR_NOT_ENOUGH_SPACE 5 +# define ESP_ERROR_UPLOAD_CANCELLED 6 +# define ESP_ERROR_FILE_CLOSE 7 +# define ESP_ERROR_NO_SD 8 -Web_Server web_server; -bool Web_Server::_setupdone = false; -uint16_t Web_Server::_port = 0; -long Web_Server::_id_connection = 0; -uint8_t Web_Server::_upload_status = UPLOAD_STATUS_NONE; -WebServer * Web_Server::_webserver = NULL; -WebSocketsServer * Web_Server::_socket_server = NULL; -#ifdef ENABLE_AUTHENTICATION -auth_ip * Web_Server::_head = NULL; -uint8_t Web_Server::_nb_ip = 0; -#define MAX_AUTH_IP 10 -#endif -Web_Server::Web_Server(){ - -} -Web_Server::~Web_Server(){ +Web_Server web_server; +bool Web_Server::_setupdone = false; +uint16_t Web_Server::_port = 0; +long Web_Server::_id_connection = 0; +uint8_t Web_Server::_upload_status = UPLOAD_STATUS_NONE; +WebServer* Web_Server::_webserver = NULL; +WebSocketsServer* Web_Server::_socket_server = NULL; +# ifdef ENABLE_AUTHENTICATION +auth_ip* Web_Server::_head = NULL; +uint8_t Web_Server::_nb_ip = 0; +# define MAX_AUTH_IP 10 +# endif +Web_Server::Web_Server() {} +Web_Server::~Web_Server() { end(); } long Web_Server::get_client_ID() { - return _id_connection; + return _id_connection; } -bool Web_Server::begin(){ - +bool Web_Server::begin() { bool no_error = true; - _setupdone = false; + _setupdone = false; if (http_enable->get() == 0) { return false; } _port = http_port->get(); //create instance - _webserver= new WebServer(_port); -#ifdef ENABLE_AUTHENTICATION + _webserver = new WebServer(_port); +# ifdef ENABLE_AUTHENTICATION //here the list of headers to be recorded - const char * headerkeys[] = {"Cookie"} ; - size_t headerkeyssize = sizeof (headerkeys) / sizeof (char*); + const char* headerkeys[] = { "Cookie" }; + size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*); //ask server to track these headers - _webserver->collectHeaders (headerkeys, headerkeyssize ); -#endif + _webserver->collectHeaders(headerkeys, headerkeyssize); +# endif _socket_server = new WebSocketsServer(_port + 1); _socket_server->begin(); _socket_server->onEvent(handle_Websocket_Event); - //Websocket output - Serial2Socket.attachWS(_socket_server); - + Serial2Socket.attachWS(_socket_server); + //events functions //_web_events->onConnect(handle_onevent_connect); //events management - // _webserver->addHandler(_web_events); - + // _webserver->addHandler(_web_events); + //Websocket function //_web_socket->onEvent(handle_Websocket_Event); //Websocket management //_webserver->addHandler(_web_socket); - + //Web server handlers //trick to catch command line on "/" before file being processed - _webserver->on("/",HTTP_ANY, handle_root); - + _webserver->on("/", HTTP_ANY, handle_root); + //Page not found handler - _webserver->onNotFound (handle_not_found); - + _webserver->onNotFound(handle_not_found); + //need to be there even no authentication to say to UI no authentication _webserver->on("/login", HTTP_ANY, handle_login); - + //web commands - _webserver->on ("/command", HTTP_ANY, handle_web_command); - _webserver->on ("/command_silent", HTTP_ANY, handle_web_command_silent); - + _webserver->on("/command", HTTP_ANY, handle_web_command); + _webserver->on("/command_silent", HTTP_ANY, handle_web_command_silent); + //SPIFFS - _webserver->on ("/files", HTTP_ANY, handleFileList, SPIFFSFileupload); - + _webserver->on("/files", HTTP_ANY, handleFileList, SPIFFSFileupload); + //web update - _webserver->on ("/updatefw", HTTP_ANY, handleUpdate, WebUpdateUpload); - -#ifdef ENABLE_SD_CARD + _webserver->on("/updatefw", HTTP_ANY, handleUpdate, WebUpdateUpload); + +# ifdef ENABLE_SD_CARD //Direct SD management - _webserver->on("/upload", HTTP_ANY, handle_direct_SDFileList,SDFile_direct_upload); + _webserver->on("/upload", HTTP_ANY, handle_direct_SDFileList, SDFile_direct_upload); //_webserver->on("/SD", HTTP_ANY, handle_SDCARD); -#endif - -#ifdef ENABLE_CAPTIVE_PORTAL - if(WiFi.getMode() == WIFI_AP){ +# endif + +# ifdef ENABLE_CAPTIVE_PORTAL + if (WiFi.getMode() == WIFI_AP) { // if DNSServer is started with "*" for domain name, it will reply with // provided IP to all DNS request dnsServer.start(DNS_PORT, "*", WiFi.softAPIP()); - grbl_send(CLIENT_ALL,"[MSG:Captive Portal Started]\r\n"); - _webserver->on ("/generate_204", HTTP_ANY, handle_root); - _webserver->on ("/gconnectivitycheck.gstatic.com", HTTP_ANY, handle_root); + grbl_send(CLIENT_ALL, "[MSG:Captive Portal Started]\r\n"); + _webserver->on("/generate_204", HTTP_ANY, handle_root); + _webserver->on("/gconnectivitycheck.gstatic.com", HTTP_ANY, handle_root); //do not forget the / at the end - _webserver->on ("/fwlink/", HTTP_ANY, handle_root); - } -#endif - -#ifdef ENABLE_SSDP + _webserver->on("/fwlink/", HTTP_ANY, handle_root); + } +# endif + +# ifdef ENABLE_SSDP //SSDP service presentation - if(WiFi.getMode() == WIFI_STA){ - _webserver->on ("/description.xml", HTTP_GET, handle_SSDP); + if (WiFi.getMode() == WIFI_STA) { + _webserver->on("/description.xml", HTTP_GET, handle_SSDP); //Add specific for SSDP - SSDP.setSchemaURL ("description.xml"); - SSDP.setHTTPPort (_port); - SSDP.setName (wifi_config.Hostname()); - SSDP.setURL ("/"); - SSDP.setDeviceType ("upnp:rootdevice"); + SSDP.setSchemaURL("description.xml"); + SSDP.setHTTPPort(_port); + SSDP.setName(wifi_config.Hostname()); + SSDP.setURL("/"); + SSDP.setDeviceType("upnp:rootdevice"); /*Any customization could be here SSDP.setModelName (ESP32_MODEL_NAME); SSDP.setModelURL (ESP32_MODEL_URL); @@ -197,34 +200,34 @@ bool Web_Server::begin(){ SSDP.setManufacturer (ESP_MANUFACTURER_NAME); SSDP.setManufacturerURL (ESP_MANUFACTURER_URL); */ - + //Start SSDP - grbl_send(CLIENT_ALL,"[MSG:SSDP Started]\r\n"); + grbl_send(CLIENT_ALL, "[MSG:SSDP Started]\r\n"); SSDP.begin(); } -#endif - grbl_send(CLIENT_ALL,"[MSG:HTTP Started]\r\n"); +# endif + grbl_send(CLIENT_ALL, "[MSG:HTTP Started]\r\n"); //start webserver _webserver->begin(); -#ifdef ENABLE_MDNS +# ifdef ENABLE_MDNS //add mDNS - if(WiFi.getMode() == WIFI_STA){ - MDNS.addService("http","tcp",_port); + if (WiFi.getMode() == WIFI_STA) { + MDNS.addService("http", "tcp", _port); } -#endif +# endif _setupdone = true; - return no_error; + return no_error; } -void Web_Server::end(){ +void Web_Server::end() { _setupdone = false; -#ifdef ENABLE_SSDP +# ifdef ENABLE_SSDP SSDP.end(); -#endif //ENABLE_SSDP -#ifdef ENABLE_MDNS +# endif //ENABLE_SSDP +# ifdef ENABLE_MDNS //remove mDNS mdns_service_remove("_http", "_tcp"); -#endif +# endif if (_socket_server) { delete _socket_server; _socket_server = NULL; @@ -233,235 +236,251 @@ void Web_Server::end(){ delete _webserver; _webserver = NULL; } -#ifdef ENABLE_AUTHENTICATION +# ifdef ENABLE_AUTHENTICATION while (_head) { - auth_ip * current = _head; - _head = _head->_next; + auth_ip* current = _head; + _head = _head->_next; delete current; } _nb_ip = 0; -#endif +# endif } //Root of Webserver///////////////////////////////////////////////////// -void Web_Server::handle_root() -{ - String path = "/index.html"; - String contentType = getContentType(path); - String pathWithGz = path + ".gz"; +void Web_Server::handle_root() { + String path = "/index.html"; + String contentType = getContentType(path); + String pathWithGz = path + ".gz"; //if have a index.html or gzip version this is default root page - if((SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) && !_webserver->hasArg("forcefallback") && _webserver->arg("forcefallback")!="yes") { - if(SPIFFS.exists(pathWithGz)) { + if ((SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) && !_webserver->hasArg("forcefallback") && + _webserver->arg("forcefallback") != "yes") { + if (SPIFFS.exists(pathWithGz)) { path = pathWithGz; } - File file = SPIFFS.open(path, FILE_READ); + File file = SPIFFS.open(path, FILE_READ); _webserver->streamFile(file, contentType); file.close(); return; } //if no lets launch the default content _webserver->sendHeader("Content-Encoding", "gzip"); - _webserver->send_P(200,"text/html",PAGE_NOFILES,PAGE_NOFILES_SIZE); + _webserver->send_P(200, "text/html", PAGE_NOFILES, PAGE_NOFILES_SIZE); } //Handle not registred path on SPIFFS neither SD /////////////////////// -void Web_Server:: handle_not_found() -{ +void Web_Server::handle_not_found() { if (is_authenticated() == LEVEL_GUEST) { _webserver->sendContent_P("HTTP/1.1 301 OK\r\nLocation: /\r\nCache-Control: no-cache\r\n\r\n"); //_webserver->client().stop(); return; } - bool page_not_found = false; - String path = _webserver->urlDecode(_webserver->uri()); - String contentType = getContentType(path); - String pathWithGz = path + ".gz"; + bool page_not_found = false; + String path = _webserver->urlDecode(_webserver->uri()); + String contentType = getContentType(path); + String pathWithGz = path + ".gz"; -#ifdef ENABLE_SD_CARD - if ((path.substring(0,4) == "/SD/")) { +# ifdef ENABLE_SD_CARD + if ((path.substring(0, 4) == "/SD/")) { //remove /SD path = path.substring(3); - if(SD.exists((char *)pathWithGz.c_str()) || SD.exists((char *)path.c_str())) { - if(SD.exists((char *)pathWithGz.c_str())) { + if (SD.exists((char*)pathWithGz.c_str()) || SD.exists((char*)path.c_str())) { + if (SD.exists((char*)pathWithGz.c_str())) { path = pathWithGz; } - File datafile = SD.open((char *)path.c_str()); + File datafile = SD.open((char*)path.c_str()); if (datafile) { vTaskDelay(1 / portTICK_RATE_MS); size_t totalFileSize = datafile.size(); - size_t i = 0; - bool done = false; + size_t i = 0; + bool done = false; _webserver->setContentLength(totalFileSize); _webserver->send(200, contentType, ""); uint8_t buf[1024]; - while (!done){ + while (!done) { vTaskDelay(1 / portTICK_RATE_MS); - int v = datafile.read(buf,1024); - if ((v == -1) || (v == 0)) { + int v = datafile.read(buf, 1024); + if ((v == -1) || (v == 0)) { done = true; } else { - _webserver->client().write(buf,1024); - i+=v; + _webserver->client().write(buf, 1024); + i += v; } - if (i >= totalFileSize) done = true; + if (i >= totalFileSize) + done = true; } datafile.close(); - if ( i != totalFileSize) { - //error: TBD - } - return; + if (i != totalFileSize) { + //error: TBD } - } + return; + } + } String content = "cannot find "; - content+=path; - _webserver->send(404,"text/plain",content.c_str()); + content += path; + _webserver->send(404, "text/plain", content.c_str()); return; } else -#endif - if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) { - if(SPIFFS.exists(pathWithGz)) { - path = pathWithGz; - } - File file = SPIFFS.open(path, FILE_READ); - _webserver->streamFile(file, contentType); - file.close(); - return; - } else { - page_not_found = true; +# endif + if (SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) { + if (SPIFFS.exists(pathWithGz)) { + path = pathWithGz; } + File file = SPIFFS.open(path, FILE_READ); + _webserver->streamFile(file, contentType); + file.close(); + return; + } else { + page_not_found = true; + } - if (page_not_found ) { -#ifdef ENABLE_CAPTIVE_PORTAL - if(WiFi.getMode() == WIFI_AP) { - String contentType= PAGE_CAPTIVE; - String stmp = WiFi.softAPIP().toString(); + if (page_not_found) { +# ifdef ENABLE_CAPTIVE_PORTAL + if (WiFi.getMode() == WIFI_AP) { + String contentType = PAGE_CAPTIVE; + String stmp = WiFi.softAPIP().toString(); //Web address = ip + port - String KEY_IP = "$WEB_ADDRESS$"; + String KEY_IP = "$WEB_ADDRESS$"; String KEY_QUERY = "$QUERY$"; if (_port != 80) { - stmp+=":"; - stmp+=String(_port); + stmp += ":"; + stmp += String(_port); } - contentType.replace(KEY_IP,stmp); - contentType.replace(KEY_IP,stmp); - contentType.replace(KEY_QUERY,_webserver->uri()); - _webserver->send(200,"text/html",contentType); + contentType.replace(KEY_IP, stmp); + contentType.replace(KEY_IP, stmp); + contentType.replace(KEY_QUERY, _webserver->uri()); + _webserver->send(200, "text/html", contentType); //_webserver->sendContent_P(NOT_AUTH_NF); //_webserver->client().stop(); return; } -#endif - path = "/404.htm"; - contentType = getContentType(path); - pathWithGz = path + ".gz"; - if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) { - if(SPIFFS.exists(pathWithGz)) { +# endif + path = "/404.htm"; + contentType = getContentType(path); + pathWithGz = path + ".gz"; + if (SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) { + if (SPIFFS.exists(pathWithGz)) { path = pathWithGz; } File file = SPIFFS.open(path, FILE_READ); _webserver->streamFile(file, contentType); file.close(); - + } else { //if not template use default page contentType = PAGE_404; String stmp; - if (WiFi.getMode()==WIFI_STA ) { - stmp=WiFi.localIP().toString(); + if (WiFi.getMode() == WIFI_STA) { + stmp = WiFi.localIP().toString(); } else { - stmp=WiFi.softAPIP().toString(); + stmp = WiFi.softAPIP().toString(); } //Web address = ip + port - String KEY_IP = "$WEB_ADDRESS$"; + String KEY_IP = "$WEB_ADDRESS$"; String KEY_QUERY = "$QUERY$"; - if ( _port != 80) { - stmp+=":"; - stmp+=String(_port); + if (_port != 80) { + stmp += ":"; + stmp += String(_port); } - contentType.replace(KEY_IP,stmp); - contentType.replace(KEY_QUERY,_webserver->uri()); - _webserver->send(200,"text/html",contentType); + contentType.replace(KEY_IP, stmp); + contentType.replace(KEY_QUERY, _webserver->uri()); + _webserver->send(200, "text/html", contentType); } } } -#ifdef ENABLE_SSDP +# ifdef ENABLE_SSDP //http SSDP xml presentation -void Web_Server::handle_SSDP () -{ - StreamString sschema ; - if (sschema.reserve (1024) ) { - String templ = "" - "" - "" - "1" - "0" - "" - "http://%s:%u/" - "" - "upnp:rootdevice" - "%s" - "/" - "%s" - "ESP32" - "Marlin" - "http://espressif.com/en/products/hardware/esp-wroom-32/overview" - "Espressif Systems" - "http://espressif.com" - "uuid:%s" - "" - "\r\n" - "\r\n"; - char uuid[37]; - String sip = WiFi.localIP().toString(); - uint32_t chipId = (uint16_t) (ESP.getEfuseMac() >> 32); - sprintf (uuid, "38323636-4558-4dda-9188-cda0e6%02x%02x%02x", - (uint16_t) ( (chipId >> 16) & 0xff), - (uint16_t) ( (chipId >> 8) & 0xff), - (uint16_t) chipId & 0xff ); - String serialNumber = String (chipId); - sschema.printf (templ.c_str(), - sip.c_str(), - _port, - wifi_config.Hostname().c_str(), - serialNumber.c_str(), - uuid); - _webserver->send (200, "text/xml", (String) sschema); +void Web_Server::handle_SSDP() { + StreamString sschema; + if (sschema.reserve(1024)) { + String templ = "" + "" + "" + "1" + "0" + "" + "http://%s:%u/" + "" + "upnp:rootdevice" + "%s" + "/" + "%s" + "ESP32" + "Marlin" + "http://espressif.com/en/products/hardware/esp-wroom-32/overview" + "Espressif Systems" + "http://espressif.com" + "uuid:%s" + "" + "\r\n" + "\r\n"; + char uuid[37]; + String sip = WiFi.localIP().toString(); + uint32_t chipId = (uint16_t)(ESP.getEfuseMac() >> 32); + sprintf(uuid, + "38323636-4558-4dda-9188-cda0e6%02x%02x%02x", + (uint16_t)((chipId >> 16) & 0xff), + (uint16_t)((chipId >> 8) & 0xff), + (uint16_t)chipId & 0xff); + String serialNumber = String(chipId); + sschema.printf(templ.c_str(), sip.c_str(), _port, wifi_config.Hostname().c_str(), serialNumber.c_str(), uuid); + _webserver->send(200, "text/xml", (String)sschema); } else { - _webserver->send (500); + _webserver->send(500); } } -#endif +# endif -bool Web_Server::is_realtime_cmd(char c){ - if (c == CMD_STATUS_REPORT) return true; - if (c == CMD_CYCLE_START) return true; - if (c == CMD_RESET) return true; - if (c == CMD_FEED_HOLD) return true; - if (c == CMD_SAFETY_DOOR) return true; - if (c == CMD_JOG_CANCEL) return true; - if (c == CMD_DEBUG_REPORT) return true; - if (c == CMD_FEED_OVR_RESET) return true; - if (c == CMD_FEED_OVR_COARSE_PLUS) return true; - if (c == CMD_FEED_OVR_COARSE_MINUS) return true; - if (c == CMD_FEED_OVR_FINE_PLUS) return true; - if (c == CMD_FEED_OVR_FINE_MINUS) return true; - if (c == CMD_RAPID_OVR_RESET) return true; - if (c == CMD_RAPID_OVR_MEDIUM) return true; - if (c == CMD_RAPID_OVR_LOW) return true; - if (c == CMD_SPINDLE_OVR_COARSE_PLUS) return true; - if (c == CMD_SPINDLE_OVR_COARSE_MINUS) return true; - if (c == CMD_SPINDLE_OVR_FINE_PLUS) return true; - if (c == CMD_SPINDLE_OVR_FINE_MINUS) return true; - if (c == CMD_SPINDLE_OVR_STOP) return true; - if (c == CMD_COOLANT_FLOOD_OVR_TOGGLE) return true; - if (c == CMD_COOLANT_MIST_OVR_TOGGLE) return true; +bool Web_Server::is_realtime_cmd(char c) { + if (c == CMD_STATUS_REPORT) + return true; + if (c == CMD_CYCLE_START) + return true; + if (c == CMD_RESET) + return true; + if (c == CMD_FEED_HOLD) + return true; + if (c == CMD_SAFETY_DOOR) + return true; + if (c == CMD_JOG_CANCEL) + return true; + if (c == CMD_DEBUG_REPORT) + return true; + if (c == CMD_FEED_OVR_RESET) + return true; + if (c == CMD_FEED_OVR_COARSE_PLUS) + return true; + if (c == CMD_FEED_OVR_COARSE_MINUS) + return true; + if (c == CMD_FEED_OVR_FINE_PLUS) + return true; + if (c == CMD_FEED_OVR_FINE_MINUS) + return true; + if (c == CMD_RAPID_OVR_RESET) + return true; + if (c == CMD_RAPID_OVR_MEDIUM) + return true; + if (c == CMD_RAPID_OVR_LOW) + return true; + if (c == CMD_SPINDLE_OVR_COARSE_PLUS) + return true; + if (c == CMD_SPINDLE_OVR_COARSE_MINUS) + return true; + if (c == CMD_SPINDLE_OVR_FINE_PLUS) + return true; + if (c == CMD_SPINDLE_OVR_FINE_MINUS) + return true; + if (c == CMD_SPINDLE_OVR_STOP) + return true; + if (c == CMD_COOLANT_FLOOD_OVR_TOGGLE) + return true; + if (c == CMD_COOLANT_MIST_OVR_TOGGLE) + return true; return false; } -void Web_Server::_handle_web_command (bool silent) -{ +void Web_Server::_handle_web_command(bool silent) { //to save time if already disconnected //if (_webserver->hasArg ("PAGEID") ) { // if (_webserver->arg ("PAGEID").length() > 0 ) { @@ -472,29 +491,29 @@ void Web_Server::_handle_web_command (bool silent) // } //} auth_t auth_level = is_authenticated(); - String cmd = ""; - if (_webserver->hasArg ("plain")) { - cmd = _webserver->arg ("plain"); - } else if (_webserver->hasArg ("commandText")) { - cmd = _webserver->arg ("commandText"); + String cmd = ""; + if (_webserver->hasArg("plain")) { + cmd = _webserver->arg("plain"); + } else if (_webserver->hasArg("commandText")) { + cmd = _webserver->arg("commandText"); } else { - _webserver->send (200, "text/plain", "Invalid command"); + _webserver->send(200, "text/plain", "Invalid command"); return; } //if it is internal command [ESPXXX] cmd.trim(); - int ESPpos = cmd.indexOf ("[ESP"); + int ESPpos = cmd.indexOf("[ESP"); if (ESPpos > -1) { char line[256]; strncpy(line, cmd.c_str(), 255); ESPResponseStream* espresponse = silent ? NULL : new ESPResponseStream(_webserver); - err_t err = system_execute_line(line, espresponse, auth_level); - String answer; + err_t err = system_execute_line(line, espresponse, auth_level); + String answer; if (err == STATUS_OK) { answer = "ok"; } else { const char* msg = errorString(err); - answer = "Error: "; + answer = "Error: "; if (msg) { answer += msg; } else { @@ -502,66 +521,63 @@ void Web_Server::_handle_web_command (bool silent) } } if (silent || !espresponse->anyOutput()) { - _webserver->send (err ? 401 : 200, "text/plain", answer.c_str()); + _webserver->send(err ? 401 : 200, "text/plain", answer.c_str()); } else { espresponse->flush(); } - } else { //execute GCODE + } else { //execute GCODE if (auth_level == LEVEL_GUEST) { - _webserver->send (401, "text/plain", "Authentication failed!\n"); + _webserver->send(401, "text/plain", "Authentication failed!\n"); return; } //Instead of send several commands one by one by web / send full set and split here - String scmd; - const char *res = ""; - uint8_t sindex = 0; + String scmd; + const char* res = ""; + uint8_t sindex = 0; // TODO Settings - this is very inefficient. get_Splited_Value() is O(n^2) // when it could easily be O(n). Also, it would be just as easy to push // the entire string into Serial2Socket and pull off lines from there. - for (uint8_t sindex = 0; - (scmd = get_Splited_Value(cmd,'\n', sindex)) != ""; - sindex++) { + for (uint8_t sindex = 0; (scmd = get_Splited_Value(cmd, '\n', sindex)) != ""; sindex++) { // 0xC2 is an HTML encoding prefix that, in UTF-8 mode, // precede 0x90 and 0xa0-0bf, which are GRBL realtime commands. // There are other encodings for 0x91-0x9f, so I am not sure // how - or whether - those commands work. // Ref: https://www.w3schools.com/tags/ref_urlencode.ASP if (!silent && (scmd.length() == 2) && (scmd[0] == 0xC2)) { - scmd[0]=scmd[1]; - scmd.remove(1,1); + scmd[0] = scmd[1]; + scmd.remove(1, 1); } if (scmd.length() > 1) scmd += "\n"; - else if (!is_realtime_cmd(scmd[0]) ) + else if (!is_realtime_cmd(scmd[0])) scmd += "\n"; if (!Serial2Socket.push(scmd.c_str())) res = "Error"; } - _webserver->send (200, "text/plain", res); + _webserver->send(200, "text/plain", res); } } //login status check -void Web_Server::handle_login() -{ -#ifdef ENABLE_AUTHENTICATION +void Web_Server::handle_login() { +# ifdef ENABLE_AUTHENTICATION String smsg; - String sUser,sPassword; + String sUser, sPassword; String auths; - int code = 200; - bool msg_alert_error=false; + int code = 200; + bool msg_alert_error = false; //disconnect can be done anytime no need to check credential if (_webserver->hasArg("DISCONNECT")) { String cookie = _webserver->header("Cookie"); - int pos = cookie.indexOf("ESPSESSIONID="); + int pos = cookie.indexOf("ESPSESSIONID="); String sessionID; - if (pos!= -1) { - int pos2 = cookie.indexOf(";",pos); - sessionID = cookie.substring(pos+strlen("ESPSESSIONID="),pos2); - } + if (pos != -1) { + int pos2 = cookie.indexOf(";", pos); + sessionID = cookie.substring(pos + strlen("ESPSESSIONID="), pos2); + } ClearAuthIP(_webserver->client().remoteIP(), sessionID.c_str()); - _webserver->sendHeader("Set-Cookie","ESPSESSIONID=0"); - _webserver->sendHeader("Cache-Control","no-cache"); + _webserver->sendHeader("Set-Cookie", "ESPSESSIONID=0"); + _webserver->sendHeader("Cache-Control", "no-cache"); String buffer2send = "{\"status\":\"Ok\",\"authentication_lvl\":\"guest\"}"; _webserver->send(code, "application/json", buffer2send); //_webserver->client().stop(); @@ -569,149 +585,147 @@ void Web_Server::handle_login() } auth_t auth_level = is_authenticated(); - if (auth_level == LEVEL_GUEST) auths = "guest"; - else if (auth_level == LEVEL_USER) auths = "user"; - else if (auth_level == LEVEL_ADMIN) auths = "admin"; - else auths = "???"; + if (auth_level == LEVEL_GUEST) + auths = "guest"; + else if (auth_level == LEVEL_USER) + auths = "user"; + else if (auth_level == LEVEL_ADMIN) + auths = "admin"; + else + auths = "???"; //check is it is a submission or a query if (_webserver->hasArg("SUBMIT")) { //is there a correct list of query? - if ( _webserver->hasArg("PASSWORD") && _webserver->hasArg("USER")) { + if (_webserver->hasArg("PASSWORD") && _webserver->hasArg("USER")) { //USER sUser = _webserver->arg("USER"); - if ( !((sUser == DEFAULT_ADMIN_LOGIN) || (sUser == DEFAULT_USER_LOGIN))) { - msg_alert_error=true; - smsg = "Error : Incorrect User"; - code = 401; + if (!((sUser == DEFAULT_ADMIN_LOGIN) || (sUser == DEFAULT_USER_LOGIN))) { + msg_alert_error = true; + smsg = "Error : Incorrect User"; + code = 401; } if (msg_alert_error == false) { //Password - sPassword = _webserver->arg("PASSWORD"); + sPassword = _webserver->arg("PASSWORD"); String sadminPassword = admin_password->get(); - String suserPassword = user_password->get(); + String suserPassword = user_password->get(); - if(!(((sUser == DEFAULT_ADMIN_LOGIN) && (strcmp(sPassword.c_str(),sadminPassword.c_str()) == 0)) || - ((sUser == DEFAULT_USER_LOGIN) && (strcmp(sPassword.c_str(),suserPassword.c_str()) == 0)))) { - msg_alert_error=true; - smsg = "Error: Incorrect password"; - code = 401; + if (!(((sUser == DEFAULT_ADMIN_LOGIN) && (strcmp(sPassword.c_str(), sadminPassword.c_str()) == 0)) || + ((sUser == DEFAULT_USER_LOGIN) && (strcmp(sPassword.c_str(), suserPassword.c_str()) == 0)))) { + msg_alert_error = true; + smsg = "Error: Incorrect password"; + code = 401; } } } else { - msg_alert_error=true; - smsg = "Error: Missing data"; - code = 500; + msg_alert_error = true; + smsg = "Error: Missing data"; + code = 500; } //change password - if (_webserver->hasArg("PASSWORD") && _webserver->hasArg("USER") && _webserver->hasArg("NEWPASSWORD") && (msg_alert_error==false) ) { - String newpassword = _webserver->arg("NEWPASSWORD"); - if (COMMANDS::isLocalPasswordValid((char *)newpassword.c_str())) { + if (_webserver->hasArg("PASSWORD") && _webserver->hasArg("USER") && _webserver->hasArg("NEWPASSWORD") && (msg_alert_error == false)) { + String newpassword = _webserver->arg("NEWPASSWORD"); + if (COMMANDS::isLocalPasswordValid((char*)newpassword.c_str())) { err_t err; if (sUser == DEFAULT_ADMIN_LOGIN) { - err = admin_password->setStringValue((char *)newpassword.c_str()); + err = admin_password->setStringValue((char*)newpassword.c_str()); } else { - err = user_password->setStringValue((char *)newpassword.c_str()); + err = user_password->setStringValue((char*)newpassword.c_str()); } if (err) { - msg_alert_error = true; - smsg = "Error: Cannot apply changes"; - code = 500; + msg_alert_error = true; + smsg = "Error: Cannot apply changes"; + code = 500; } } else { - msg_alert_error=true; - smsg = "Error: Incorrect password"; - code = 500; + msg_alert_error = true; + smsg = "Error: Incorrect password"; + code = 500; } } - if ((code == 200) || (code == 500)) { - auth_t current_auth_level; - if(sUser == DEFAULT_ADMIN_LOGIN) { - current_auth_level = LEVEL_ADMIN; - } else if(sUser == DEFAULT_USER_LOGIN){ - current_auth_level = LEVEL_USER; - } else { - current_auth_level = LEVEL_GUEST; - } - //create Session - if ((current_auth_level != auth_level) || (auth_level== LEVEL_GUEST)) { - auth_ip * current_auth = new auth_ip; - current_auth->level = current_auth_level; - current_auth->ip=_webserver->client().remoteIP(); - strcpy(current_auth->sessionID,create_session_ID()); - strcpy(current_auth->userID,sUser.c_str()); - current_auth->last_time=millis(); - if (AddAuthIP(current_auth)) { - String tmps ="ESPSESSIONID="; - tmps+=current_auth->sessionID; - _webserver->sendHeader("Set-Cookie",tmps); - _webserver->sendHeader("Cache-Control","no-cache"); - switch(current_auth->level) { - case LEVEL_ADMIN: - auths = "admin"; - break; - case LEVEL_USER: - auths = "user"; - break; - default: - auths = "guest"; - break; - } + if ((code == 200) || (code == 500)) { + auth_t current_auth_level; + if (sUser == DEFAULT_ADMIN_LOGIN) { + current_auth_level = LEVEL_ADMIN; + } else if (sUser == DEFAULT_USER_LOGIN) { + current_auth_level = LEVEL_USER; } else { - delete current_auth; - msg_alert_error=true; - code = 500; - smsg = "Error: Too many connections"; + current_auth_level = LEVEL_GUEST; + } + //create Session + if ((current_auth_level != auth_level) || (auth_level == LEVEL_GUEST)) { + auth_ip* current_auth = new auth_ip; + current_auth->level = current_auth_level; + current_auth->ip = _webserver->client().remoteIP(); + strcpy(current_auth->sessionID, create_session_ID()); + strcpy(current_auth->userID, sUser.c_str()); + current_auth->last_time = millis(); + if (AddAuthIP(current_auth)) { + String tmps = "ESPSESSIONID="; + tmps += current_auth->sessionID; + _webserver->sendHeader("Set-Cookie", tmps); + _webserver->sendHeader("Cache-Control", "no-cache"); + switch (current_auth->level) { + case LEVEL_ADMIN: auths = "admin"; break; + case LEVEL_USER: auths = "user"; break; + default: auths = "guest"; break; + } + } else { + delete current_auth; + msg_alert_error = true; + code = 500; + smsg = "Error: Too many connections"; + } } } - } - if (code == 200) smsg = "Ok"; + if (code == 200) + smsg = "Ok"; - //build JSON - String buffer2send = "{\"status\":\"" + smsg + "\",\"authentication_lvl\":\""; - buffer2send += auths; - buffer2send += "\"}"; - _webserver->send(code, "application/json", buffer2send); + //build JSON + String buffer2send = "{\"status\":\"" + smsg + "\",\"authentication_lvl\":\""; + buffer2send += auths; + buffer2send += "\"}"; + _webserver->send(code, "application/json", buffer2send); } else { - if (auth_level != LEVEL_GUEST) { - String cookie = _webserver->header("Cookie"); - int pos = cookie.indexOf("ESPSESSIONID="); - String sessionID; - if (pos!= -1) { - int pos2 = cookie.indexOf(";",pos); - sessionID = cookie.substring(pos+strlen("ESPSESSIONID="),pos2); - auth_ip * current_auth_info = GetAuth(_webserver->client().remoteIP(), sessionID.c_str()); - if (current_auth_info != NULL){ + if (auth_level != LEVEL_GUEST) { + String cookie = _webserver->header("Cookie"); + int pos = cookie.indexOf("ESPSESSIONID="); + String sessionID; + if (pos != -1) { + int pos2 = cookie.indexOf(";", pos); + sessionID = cookie.substring(pos + strlen("ESPSESSIONID="), pos2); + auth_ip* current_auth_info = GetAuth(_webserver->client().remoteIP(), sessionID.c_str()); + if (current_auth_info != NULL) { sUser = current_auth_info->userID; } + } } + String buffer2send = "{\"status\":\"200\",\"authentication_lvl\":\""; + buffer2send += auths; + buffer2send += "\",\"user\":\""; + buffer2send += sUser; + buffer2send += "\"}"; + _webserver->send(code, "application/json", buffer2send); } - String buffer2send = "{\"status\":\"200\",\"authentication_lvl\":\""; - buffer2send += auths; - buffer2send += "\",\"user\":\""; - buffer2send += sUser; - buffer2send +="\"}"; - _webserver->send(code, "application/json", buffer2send); - } -#else - _webserver->sendHeader("Cache-Control","no-cache"); +# else + _webserver->sendHeader("Cache-Control", "no-cache"); _webserver->send(200, "application/json", "{\"status\":\"Ok\",\"authentication_lvl\":\"admin\"}"); -#endif +# endif } //SPIFFS //SPIFFS files list and file commands -void Web_Server::handleFileList () -{ +void Web_Server::handleFileList() { auth_t auth_level = is_authenticated(); if (auth_level == LEVEL_GUEST) { _upload_status = UPLOAD_STATUS_NONE; - _webserver->send (401, "text/plain", "Authentication failed!\n"); + _webserver->send(401, "text/plain", "Authentication failed!\n"); return; } - String path ; + String path; String status = "Ok"; if (_upload_status == UPLOAD_STATUS_FAILED) { - status = "Upload failed"; + status = "Upload failed"; _upload_status = UPLOAD_STATUS_NONE; } _upload_status = UPLOAD_STATUS_NONE; @@ -722,92 +736,92 @@ void Web_Server::handleFileList () path = "/user"; } //get current path - if (_webserver->hasArg ("path") ) { - path += _webserver->arg ("path") ; + if (_webserver->hasArg("path")) { + path += _webserver->arg("path"); } //to have a clean path path.trim(); - path.replace ("//", "/"); + path.replace("//", "/"); if (path[path.length() - 1] != '/') { path += "/"; } //check if query need some action - if (_webserver->hasArg ("action") ) { + if (_webserver->hasArg("action")) { //delete a file - if (_webserver->arg ("action") == "delete" && _webserver->hasArg ("filename") ) { + if (_webserver->arg("action") == "delete" && _webserver->hasArg("filename")) { String filename; - String shortname = _webserver->arg ("filename"); - shortname.replace ("/", ""); - filename = path + _webserver->arg ("filename"); - filename.replace ("//", "/"); - if (!SPIFFS.exists (filename) ) { + String shortname = _webserver->arg("filename"); + shortname.replace("/", ""); + filename = path + _webserver->arg("filename"); + filename.replace("//", "/"); + if (!SPIFFS.exists(filename)) { status = shortname + " does not exists!"; } else { - if (SPIFFS.remove (filename) ) { + if (SPIFFS.remove(filename)) { status = shortname + " deleted"; //what happen if no "/." and no other subfiles ? String ptmp = path; - if ( (path != "/") && (path[path.length() - 1] = '/') ) { - ptmp = path.substring (0, path.length() - 1); + if ((path != "/") && (path[path.length() - 1] = '/')) { + ptmp = path.substring(0, path.length() - 1); } - File dir = SPIFFS.open (ptmp); + File dir = SPIFFS.open(ptmp); File dircontent = dir.openNextFile(); if (!dircontent) { //keep directory alive even empty - File r = SPIFFS.open (path + "/.", FILE_WRITE); + File r = SPIFFS.open(path + "/.", FILE_WRITE); if (r) { r.close(); } } } else { - status = "Cannot deleted " ; - status += shortname ; + status = "Cannot deleted "; + status += shortname; } } } //delete a directory - if (_webserver->arg ("action") == "deletedir" && _webserver->hasArg ("filename") ) { + if (_webserver->arg("action") == "deletedir" && _webserver->hasArg("filename")) { String filename; - String shortname = _webserver->arg ("filename"); - shortname.replace ("/", ""); - filename = path + _webserver->arg ("filename"); + String shortname = _webserver->arg("filename"); + shortname.replace("/", ""); + filename = path + _webserver->arg("filename"); filename += "/"; - filename.replace ("//", "/"); + filename.replace("//", "/"); if (filename != "/") { bool delete_error = false; - File dir = SPIFFS.open (path + shortname); + File dir = SPIFFS.open(path + shortname); { File file2deleted = dir.openNextFile(); while (file2deleted) { String fullpath = file2deleted.name(); - if (!SPIFFS.remove (fullpath) ) { + if (!SPIFFS.remove(fullpath)) { delete_error = true; - status = "Cannot deleted " ; + status = "Cannot deleted "; status += fullpath; } file2deleted = dir.openNextFile(); } } if (!delete_error) { - status = shortname ; + status = shortname; status += " deleted"; } } } //create a directory - if (_webserver->arg ("action") == "createdir" && _webserver->hasArg ("filename") ) { + if (_webserver->arg("action") == "createdir" && _webserver->hasArg("filename")) { String filename; - filename = path + _webserver->arg ("filename") + "/."; - String shortname = _webserver->arg ("filename"); - shortname.replace ("/", ""); - filename.replace ("//", "/"); - if (SPIFFS.exists (filename) ) { + filename = path + _webserver->arg("filename") + "/."; + String shortname = _webserver->arg("filename"); + shortname.replace("/", ""); + filename.replace("//", "/"); + if (SPIFFS.exists(filename)) { status = shortname + " already exists!"; } else { - File r = SPIFFS.open (filename, FILE_WRITE); + File r = SPIFFS.open(filename, FILE_WRITE); if (!r) { status = "Cannot create "; - status += shortname ; + status += shortname; } else { r.close(); status = shortname + " created"; @@ -816,42 +830,42 @@ void Web_Server::handleFileList () } } String jsonfile = "{"; - String ptmp = path; - if ( (path != "/") && (path[path.length() - 1] = '/') ) { - ptmp = path.substring (0, path.length() - 1); + String ptmp = path; + if ((path != "/") && (path[path.length() - 1] = '/')) { + ptmp = path.substring(0, path.length() - 1); } - File dir = SPIFFS.open (ptmp); + File dir = SPIFFS.open(ptmp); jsonfile += "\"files\":["; - bool firstentry = true; + bool firstentry = true; String subdirlist = ""; - File fileparsed = dir.openNextFile(); + File fileparsed = dir.openNextFile(); while (fileparsed) { - String filename = fileparsed.name(); - String size = ""; - bool addtolist = true; + String filename = fileparsed.name(); + String size = ""; + bool addtolist = true; //remove path from name - filename = filename.substring (path.length(), filename.length() ); + filename = filename.substring(path.length(), filename.length()); //check if file or subfile - if (filename.indexOf ("/") > -1) { + if (filename.indexOf("/") > -1) { //Do not rely on "/." to define directory as SPIFFS upload won't create it but directly files //and no need to overload SPIFFS if not necessary to create "/." if no need //it will reduce SPIFFS available space so limit it to creation - filename = filename.substring (0, filename.indexOf ("/") ); + filename = filename.substring(0, filename.indexOf("/")); String tag = "*"; tag += filename + "*"; - if (subdirlist.indexOf (tag) > -1 || filename.length() == 0) { //already in list - addtolist = false; //no need to add + if (subdirlist.indexOf(tag) > -1 || filename.length() == 0) { //already in list + addtolist = false; //no need to add } else { - size = "-1"; //it is subfile so display only directory, size will be -1 to describe it is directory + size = "-1"; //it is subfile so display only directory, size will be -1 to describe it is directory if (subdirlist.length() == 0) { subdirlist += "*"; } - subdirlist += filename + "*"; //add to list + subdirlist += filename + "*"; //add to list } } else { //do not add "." file - if (! ( (filename == ".") || (filename == "") ) ) { - size = ESPResponseStream::formatBytes (fileparsed.size() ); + if (!((filename == ".") || (filename == ""))) { + size = ESPResponseStream::formatBytes(fileparsed.size()); } else { addtolist = false; } @@ -878,11 +892,11 @@ void Web_Server::handleFileList () size_t totalBytes; size_t usedBytes; totalBytes = SPIFFS.totalBytes(); - usedBytes = SPIFFS.usedBytes(); - jsonfile += "\"total\":\"" + ESPResponseStream::formatBytes (totalBytes) + "\","; - jsonfile += "\"used\":\"" + ESPResponseStream::formatBytes (usedBytes) + "\","; - jsonfile.concat (F ("\"occupation\":\"") ); - jsonfile += String (100 * usedBytes / totalBytes); + usedBytes = SPIFFS.usedBytes(); + jsonfile += "\"total\":\"" + ESPResponseStream::formatBytes(totalBytes) + "\","; + jsonfile += "\"used\":\"" + ESPResponseStream::formatBytes(usedBytes) + "\","; + jsonfile.concat(F("\"occupation\":\"")); + jsonfile += String(100 * usedBytes / totalBytes); jsonfile += "\""; jsonfile += "}"; path = ""; @@ -892,15 +906,15 @@ void Web_Server::handleFileList () } //push error code and message to websocket -void Web_Server::pushError(int code, const char * st, bool web_error, uint16_t timeout){ +void Web_Server::pushError(int code, const char* st, bool web_error, uint16_t timeout) { if (_socket_server && st) { String s = "ERROR:" + String(code) + ":"; - s+=st; + s += st; _socket_server->sendTXT(_id_connection, s); if (web_error != 0) { if (_webserver) { if (_webserver->client().available() > 0) { - _webserver->send (web_error, "text/xml", st); + _webserver->send(web_error, "text/xml", st); } } } @@ -913,62 +927,62 @@ void Web_Server::pushError(int code, const char * st, bool web_error, uint16_t t } //abort reception of packages -void Web_Server::cancelUpload(){ +void Web_Server::cancelUpload() { if (_webserver) { if (_webserver->client().available() > 0) { HTTPUpload& upload = _webserver->upload(); - upload.status = UPLOAD_FILE_ABORTED; - errno = ECONNABORTED; + upload.status = UPLOAD_FILE_ABORTED; + errno = ECONNABORTED; _webserver->client().stop(); delay(100); - } + } } } //SPIFFS files uploader handle -void Web_Server::SPIFFSFileupload () -{ +void Web_Server::SPIFFSFileupload() { static String filename; - static File fsUploadFile = (File)0; - //get authentication status - auth_t auth_level= is_authenticated(); + static File fsUploadFile = (File)0; + //get authentication status + auth_t auth_level = is_authenticated(); //Guest cannot upload - only admin if (auth_level == LEVEL_GUEST) { _upload_status = UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload rejected]\r\n"); + grbl_send(CLIENT_ALL, "[MSG:Upload rejected]\r\n"); pushError(ESP_ERROR_AUTHENTICATION, "Upload rejected", 401); } else { HTTPUpload& upload = _webserver->upload(); - if((_upload_status != UPLOAD_STATUS_FAILED)|| (upload.status == UPLOAD_FILE_START)){ + if ((_upload_status != UPLOAD_STATUS_FAILED) || (upload.status == UPLOAD_FILE_START)) { //Upload start //************** - if(upload.status == UPLOAD_FILE_START) { - _upload_status= UPLOAD_STATUS_ONGOING; + if (upload.status == UPLOAD_FILE_START) { + _upload_status = UPLOAD_STATUS_ONGOING; String upload_filename = upload.filename; - if (upload_filename[0] != '/') filename = "/" + upload_filename; - else filename = upload.filename; + if (upload_filename[0] != '/') + filename = "/" + upload_filename; + else + filename = upload.filename; //according User or Admin the root is different as user is isolate to /user when admin has full access - if(auth_level != LEVEL_ADMIN) { + if (auth_level != LEVEL_ADMIN) { upload_filename = filename; - filename = "/user" + upload_filename; + filename = "/user" + upload_filename; } - - if (SPIFFS.exists (filename) ) { - SPIFFS.remove (filename); + + if (SPIFFS.exists(filename)) { + SPIFFS.remove(filename); } - if (fsUploadFile ) { + if (fsUploadFile) { fsUploadFile.close(); } - String sizeargname = upload.filename + "S"; - if (_webserver->hasArg (sizeargname.c_str()) ) { - uint32_t filesize = _webserver->arg (sizeargname.c_str()).toInt(); - uint32_t freespace = SPIFFS.totalBytes() - SPIFFS.usedBytes(); - if (filesize > freespace) { - _upload_status=UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload error]\r\n"); + String sizeargname = upload.filename + "S"; + if (_webserver->hasArg(sizeargname.c_str())) { + uint32_t filesize = _webserver->arg(sizeargname.c_str()).toInt(); + uint32_t freespace = SPIFFS.totalBytes() - SPIFFS.usedBytes(); + if (filesize > freespace) { + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Upload error]\r\n"); pushError(ESP_ERROR_NOT_ENOUGH_SPACE, "Upload rejected, not enough space"); - } - + } } if (_upload_status != UPLOAD_STATUS_FAILED) { //create file @@ -976,91 +990,89 @@ void Web_Server::SPIFFSFileupload () //check If creation succeed if (fsUploadFile) { //if yes upload is started - _upload_status= UPLOAD_STATUS_ONGOING; + _upload_status = UPLOAD_STATUS_ONGOING; } else { //if no set cancel flag - _upload_status=UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload error]\r\n"); + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Upload error]\r\n"); pushError(ESP_ERROR_FILE_CREATION, "File creation failed"); } } //Upload write //************** - } else if(upload.status == UPLOAD_FILE_WRITE) { + } else if (upload.status == UPLOAD_FILE_WRITE) { vTaskDelay(1 / portTICK_RATE_MS); //check if file is available and no error - if(fsUploadFile && _upload_status == UPLOAD_STATUS_ONGOING) { + if (fsUploadFile && _upload_status == UPLOAD_STATUS_ONGOING) { //no error so write post date if (upload.currentSize != fsUploadFile.write(upload.buf, upload.currentSize)) { - _upload_status=UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload error]\r\n"); + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Upload error]\r\n"); pushError(ESP_ERROR_FILE_WRITE, "File write failed"); } } else { //we have a problem set flag UPLOAD_STATUS_FAILED - _upload_status=UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload error]\r\n"); + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Upload error]\r\n"); pushError(ESP_ERROR_FILE_WRITE, "File write failed"); } //Upload end //************** - } else if(upload.status == UPLOAD_FILE_END) { + } else if (upload.status == UPLOAD_FILE_END) { //check if file is still open - if(fsUploadFile) { + if (fsUploadFile) { //close it fsUploadFile.close(); - //check size - String sizeargname = upload.filename + "S"; - fsUploadFile = SPIFFS.open (filename, FILE_READ); - uint32_t filesize = fsUploadFile.size(); + //check size + String sizeargname = upload.filename + "S"; + fsUploadFile = SPIFFS.open(filename, FILE_READ); + uint32_t filesize = fsUploadFile.size(); fsUploadFile.close(); - if (_webserver->hasArg (sizeargname.c_str()) ) { - if (_webserver->arg (sizeargname.c_str()) != String(filesize)) { + if (_webserver->hasArg(sizeargname.c_str())) { + if (_webserver->arg(sizeargname.c_str()) != String(filesize)) { _upload_status = UPLOAD_STATUS_FAILED; } - } + } if (_upload_status == UPLOAD_STATUS_ONGOING) { _upload_status = UPLOAD_STATUS_SUCCESSFUL; } else { - grbl_send(CLIENT_ALL,"[MSG:Upload error]\r\n"); + grbl_send(CLIENT_ALL, "[MSG:Upload error]\r\n"); pushError(ESP_ERROR_UPLOAD, "File upload failed"); } } else { //we have a problem set flag UPLOAD_STATUS_FAILED - _upload_status=UPLOAD_STATUS_FAILED; + _upload_status = UPLOAD_STATUS_FAILED; pushError(ESP_ERROR_FILE_CLOSE, "File close failed"); - grbl_send(CLIENT_ALL,"[MSG:Upload error]\r\n"); - + grbl_send(CLIENT_ALL, "[MSG:Upload error]\r\n"); } //Upload cancelled //************** } else { - _upload_status = UPLOAD_STATUS_FAILED; - //pushError(ESP_ERROR_UPLOAD, "File upload failed"); - return; + _upload_status = UPLOAD_STATUS_FAILED; + //pushError(ESP_ERROR_UPLOAD, "File upload failed"); + return; } } } - + if (_upload_status == UPLOAD_STATUS_FAILED) { cancelUpload(); - if (SPIFFS.exists (filename) ) { - SPIFFS.remove (filename); - } + if (SPIFFS.exists(filename)) { + SPIFFS.remove(filename); } + } COMMANDS::wait(0); } -//Web Update handler -void Web_Server::handleUpdate () -{ +//Web Update handler +void Web_Server::handleUpdate() { auth_t auth_level = is_authenticated(); if (auth_level != LEVEL_ADMIN) { _upload_status = UPLOAD_STATUS_NONE; - _webserver->send (403, "text/plain", "Not allowed, log in first!\n"); + _webserver->send(403, "text/plain", "Not allowed, log in first!\n"); return; } - String jsonfile = "{\"status\":\"" ; + String jsonfile = "{\"status\":\""; jsonfile += String(_upload_status); jsonfile += "\"}"; //send status @@ -1076,27 +1088,26 @@ void Web_Server::handleUpdate () } //File upload for Web update -void Web_Server::WebUpdateUpload () -{ - static size_t last_upload_update; +void Web_Server::WebUpdateUpload() { + static size_t last_upload_update; static uint32_t maxSketchSpace = 0; //only admin can update FW if (is_authenticated() != LEVEL_ADMIN) { _upload_status = UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload rejected]\r\n"); + grbl_send(CLIENT_ALL, "[MSG:Upload rejected]\r\n"); pushError(ESP_ERROR_AUTHENTICATION, "Upload rejected", 401); } else { //get current file ID HTTPUpload& upload = _webserver->upload(); - if((_upload_status != UPLOAD_STATUS_FAILED)|| (upload.status == UPLOAD_FILE_START)){ + if ((_upload_status != UPLOAD_STATUS_FAILED) || (upload.status == UPLOAD_FILE_START)) { //Upload start //************** - if(upload.status == UPLOAD_FILE_START) { - grbl_send(CLIENT_ALL,"[MSG:Update Firmware]\r\n"); - _upload_status= UPLOAD_STATUS_ONGOING; - String sizeargname = upload.filename + "S"; - if (_webserver->hasArg (sizeargname.c_str()) ) { - maxSketchSpace = _webserver->arg (sizeargname).toInt(); + if (upload.status == UPLOAD_FILE_START) { + grbl_send(CLIENT_ALL, "[MSG:Update Firmware]\r\n"); + _upload_status = UPLOAD_STATUS_ONGOING; + String sizeargname = upload.filename + "S"; + if (_webserver->hasArg(sizeargname.c_str())) { + maxSketchSpace = _webserver->arg(sizeargname).toInt(); } //check space size_t flashsize = 0; @@ -1105,57 +1116,59 @@ void Web_Server::WebUpdateUpload () if (partition) { flashsize = partition->size; } - } + } if (flashsize < maxSketchSpace) { pushError(ESP_ERROR_NOT_ENOUGH_SPACE, "Upload rejected, not enough space"); - _upload_status=UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Update cancelled]\r\n"); + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Update cancelled]\r\n"); } if (_upload_status != UPLOAD_STATUS_FAILED) { last_upload_update = 0; - if(!Update.begin()) { //start with max available size - _upload_status=UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Update cancelled]\r\n"); + if (!Update.begin()) { //start with max available size + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Update cancelled]\r\n"); pushError(ESP_ERROR_NOT_ENOUGH_SPACE, "Upload rejected, not enough space"); } else { - grbl_send(CLIENT_ALL,"\n[MSG:Update 0%]\r\n"); + grbl_send(CLIENT_ALL, "\n[MSG:Update 0%]\r\n"); } } //Upload write //************** - } else if(upload.status == UPLOAD_FILE_WRITE) { + } else if (upload.status == UPLOAD_FILE_WRITE) { vTaskDelay(1 / portTICK_RATE_MS); //check if no error if (_upload_status == UPLOAD_STATUS_ONGOING) { - if ( ((100 * upload.totalSize) / maxSketchSpace) !=last_upload_update) { - if ( maxSketchSpace > 0)last_upload_update = (100 * upload.totalSize) / maxSketchSpace; - else last_upload_update = upload.totalSize; + if (((100 * upload.totalSize) / maxSketchSpace) != last_upload_update) { + if (maxSketchSpace > 0) + last_upload_update = (100 * upload.totalSize) / maxSketchSpace; + else + last_upload_update = upload.totalSize; String s = "Update "; - s+= String(last_upload_update); - s+="%"; - grbl_sendf(CLIENT_ALL,"[MSG:%s]\r\n", s.c_str()); + s += String(last_upload_update); + s += "%"; + grbl_sendf(CLIENT_ALL, "[MSG:%s]\r\n", s.c_str()); } - if(Update.write(upload.buf, upload.currentSize) != upload.currentSize) { - _upload_status=UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Update write failed]\r\n"); + if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Update write failed]\r\n"); pushError(ESP_ERROR_FILE_WRITE, "File write failed"); } } //Upload end //************** - } else if(upload.status == UPLOAD_FILE_END) { - if(Update.end(true)) { //true to set the size to the current progress + } else if (upload.status == UPLOAD_FILE_END) { + if (Update.end(true)) { //true to set the size to the current progress //Now Reboot - grbl_send(CLIENT_ALL,"[MSG:Update 100%]\r\n"); - _upload_status=UPLOAD_STATUS_SUCCESSFUL; + grbl_send(CLIENT_ALL, "[MSG:Update 100%]\r\n"); + _upload_status = UPLOAD_STATUS_SUCCESSFUL; } else { - _upload_status=UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Update failed]\r\n"); + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Update failed]\r\n"); pushError(ESP_ERROR_UPLOAD, "Update upload failed"); } - } else if(upload.status == UPLOAD_FILE_ABORTED) { - grbl_send(CLIENT_ALL,"[MSG:Update failed]\r\n"); - _upload_status=UPLOAD_STATUS_FAILED; + } else if (upload.status == UPLOAD_FILE_ABORTED) { + grbl_send(CLIENT_ALL, "[MSG:Update failed]\r\n"); + _upload_status = UPLOAD_STATUS_FAILED; return; } } @@ -1167,140 +1180,139 @@ void Web_Server::WebUpdateUpload () COMMANDS::wait(0); } - -#ifdef ENABLE_SD_CARD +# ifdef ENABLE_SD_CARD //Function to delete not empty directory on SD card -bool Web_Server::deleteRecursive(String path) -{ +bool Web_Server::deleteRecursive(String path) { bool result = true; - File file = SD.open((char *)path.c_str()); + File file = SD.open((char*)path.c_str()); //failed if (!file) { - return false; - } - if(!file.isDirectory()) { + return false; + } + if (!file.isDirectory()) { file.close(); //return if success or not - return SD.remove((char *)path.c_str()); + return SD.remove((char*)path.c_str()); } file.rewindDirectory(); - while(true) { + while (true) { File entry = file.openNextFile(); if (!entry) { break; } String entryPath = entry.name(); - if(entry.isDirectory()) { + if (entry.isDirectory()) { entry.close(); - if(!deleteRecursive(entryPath)) { - result = false; + if (!deleteRecursive(entryPath)) { + result = false; } } else { entry.close(); - if (!SD.remove((char *)entryPath.c_str())) { + if (!SD.remove((char*)entryPath.c_str())) { result = false; break; } } - COMMANDS::wait(0); //wdtFeed + COMMANDS::wait(0); //wdtFeed } file.close(); - if (result) return SD.rmdir((char *)path.c_str()); - else return false; + if (result) + return SD.rmdir((char*)path.c_str()); + else + return false; } //direct SD files list////////////////////////////////////////////////// -void Web_Server::handle_direct_SDFileList() -{ +void Web_Server::handle_direct_SDFileList() { //this is only for admin and user if (is_authenticated() == LEVEL_GUEST) { - _upload_status=UPLOAD_STATUS_NONE; + _upload_status = UPLOAD_STATUS_NONE; _webserver->send(401, "application/json", "{\"status\":\"Authentication failed!\"}"); return; } - String path="/"; - String sstatus="Ok"; + String path = "/"; + String sstatus = "Ok"; if ((_upload_status == UPLOAD_STATUS_FAILED) || (_upload_status == UPLOAD_STATUS_FAILED)) { - sstatus = "Upload failed"; + sstatus = "Upload failed"; _upload_status = UPLOAD_STATUS_NONE; } - bool list_files = true; + bool list_files = true; uint64_t totalspace = 0; - uint64_t usedspace = 0; + uint64_t usedspace = 0; if (get_sd_state(true) != SDCARD_IDLE) { - _webserver->sendHeader("Cache-Control","no-cache"); + _webserver->sendHeader("Cache-Control", "no-cache"); _webserver->send(200, "application/json", "{\"status\":\"No SD Card\"}"); return; } set_sd_state(SDCARD_BUSY_PARSING); //get current path - if(_webserver->hasArg("path")) { - path += _webserver->arg("path") ; + if (_webserver->hasArg("path")) { + path += _webserver->arg("path"); } //to have a clean path path.trim(); - path.replace("//","/"); - if (path[path.length()-1] !='/') { - path +="/"; + path.replace("//", "/"); + if (path[path.length() - 1] != '/') { + path += "/"; } //check if query need some action - if(_webserver->hasArg("action")) { + if (_webserver->hasArg("action")) { //delete a file - if(_webserver->arg("action") == "delete" && _webserver->hasArg("filename")) { + if (_webserver->arg("action") == "delete" && _webserver->hasArg("filename")) { String filename; String shortname = _webserver->arg("filename"); - filename = path + shortname; - shortname.replace("/",""); - filename.replace("//","/"); - if(!SD.exists((char *)filename.c_str())) { + filename = path + shortname; + shortname.replace("/", ""); + filename.replace("//", "/"); + if (!SD.exists((char*)filename.c_str())) { sstatus = shortname + " does not exist!"; } else { - if (SD.remove((char *)filename.c_str())) { + if (SD.remove((char*)filename.c_str())) { sstatus = shortname + " deleted"; } else { - sstatus = "Cannot deleted " ; - sstatus+=shortname ; + sstatus = "Cannot deleted "; + sstatus += shortname; } } } //delete a directory - if( _webserver->arg("action") == "deletedir" && _webserver->hasArg("filename")) { + if (_webserver->arg("action") == "deletedir" && _webserver->hasArg("filename")) { String filename; String shortname = _webserver->arg("filename"); - shortname.replace("/",""); + shortname.replace("/", ""); filename = path + "/" + shortname; - filename.replace("//","/"); + filename.replace("//", "/"); if (filename != "/") { - if(!SD.exists((char *)filename.c_str())) { + if (!SD.exists((char*)filename.c_str())) { sstatus = shortname + " does not exist!"; } else { if (!deleteRecursive(filename)) { - sstatus ="Error deleting: "; - sstatus += shortname ; + sstatus = "Error deleting: "; + sstatus += shortname; } else { - sstatus = shortname ; - sstatus+=" deleted"; + sstatus = shortname; + sstatus += " deleted"; } } } else { - sstatus ="Cannot delete root"; + sstatus = "Cannot delete root"; } } //create a directory - if( _webserver->arg("action")=="createdir" && _webserver->hasArg("filename")) { + if (_webserver->arg("action") == "createdir" && _webserver->hasArg("filename")) { String filename; - String shortname = _webserver->arg("filename"); - filename = path + shortname; - shortname.replace("/",""); - filename.replace("//","/"); - if(SD.exists((char *)filename.c_str())) { + String shortname = _webserver->arg("filename"); + filename = path + shortname; + shortname.replace("/", ""); + filename.replace("//", "/"); + if (SD.exists((char*)filename.c_str())) { sstatus = shortname + " already exists!"; } else { - if (!SD.mkdir((char *)filename.c_str())) { + if (!SD.mkdir((char*)filename.c_str())) { sstatus = "Cannot create "; - sstatus += shortname ; + sstatus += shortname; } else { sstatus = shortname + " created"; } @@ -1308,204 +1320,201 @@ void Web_Server::handle_direct_SDFileList() } } //check if no need build file list - if( _webserver->hasArg("dontlist")) { - if( _webserver->arg("dontlist") == "yes") { + if (_webserver->hasArg("dontlist")) { + if (_webserver->arg("dontlist") == "yes") { list_files = false; } } // TODO Settings - consider using the JSONEncoder class - String jsonfile = "{" ; - jsonfile+="\"files\":["; + String jsonfile = "{"; + jsonfile += "\"files\":["; - if (path!="/")path = path.substring(0,path.length()-1); - if (path!="/" && !SD.exists((char *)path.c_str())) { - - String s = "{\"status\":\" "; + if (path != "/") + path = path.substring(0, path.length() - 1); + if (path != "/" && !SD.exists((char*)path.c_str())) { + String s = "{\"status\":\" "; s += path; - s+= " does not exist on SD Card\"}"; - _webserver->send(200, "application/json", s.c_str()); + s += " does not exist on SD Card\"}"; + _webserver->send(200, "application/json", s.c_str()); return; } if (list_files) { - File dir = SD.open((char *)path.c_str()); - if (!dir) { - } - if(!dir.isDirectory()) { + File dir = SD.open((char*)path.c_str()); + if (!dir) {} + if (!dir.isDirectory()) { dir.close(); } dir.rewindDirectory(); - File entry = dir.openNextFile(); - int i = 0; - while(entry) { - COMMANDS::wait (1); - if (i>0) { - jsonfile+=","; + File entry = dir.openNextFile(); + int i = 0; + while (entry) { + COMMANDS::wait(1); + if (i > 0) { + jsonfile += ","; } - jsonfile+="{\"name\":\""; + jsonfile += "{\"name\":\""; String tmpname = entry.name(); - int pos = tmpname.lastIndexOf("/"); - tmpname = tmpname.substring(pos+1); - jsonfile+=tmpname; - jsonfile+="\",\"shortname\":\""; //No need here - jsonfile+=tmpname; - jsonfile+="\",\"size\":\""; + int pos = tmpname.lastIndexOf("/"); + tmpname = tmpname.substring(pos + 1); + jsonfile += tmpname; + jsonfile += "\",\"shortname\":\""; //No need here + jsonfile += tmpname; + jsonfile += "\",\"size\":\""; if (entry.isDirectory()) { - jsonfile+="-1"; + jsonfile += "-1"; } else { // files have sizes, directories do not - jsonfile+=ESPResponseStream::formatBytes(entry.size()); + jsonfile += ESPResponseStream::formatBytes(entry.size()); } - jsonfile+="\",\"datetime\":\""; + jsonfile += "\",\"datetime\":\""; //TODO - can be done later - jsonfile+="\"}"; + jsonfile += "\"}"; i++; entry.close(); - entry = dir.openNextFile(); - } + entry = dir.openNextFile(); + } dir.close(); } - jsonfile+="],\"path\":\""; - jsonfile+=path + "\","; - jsonfile+="\"total\":\""; - String stotalspace,susedspace; + jsonfile += "],\"path\":\""; + jsonfile += path + "\","; + jsonfile += "\"total\":\""; + String stotalspace, susedspace; //SDCard are in GB or MB but no less - totalspace = SD.totalBytes(); - usedspace = SD.usedBytes(); + totalspace = SD.totalBytes(); + usedspace = SD.usedBytes(); stotalspace = ESPResponseStream::formatBytes(totalspace); - susedspace = ESPResponseStream::formatBytes(usedspace+1); + susedspace = ESPResponseStream::formatBytes(usedspace + 1); - uint32_t occupedspace = 1; - uint32_t usedspace2 = usedspace/(1024*1024); - uint32_t totalspace2 = totalspace/(1024*1024); - occupedspace = (usedspace2 * 100)/totalspace2; + uint32_t occupedspace = 1; + uint32_t usedspace2 = usedspace / (1024 * 1024); + uint32_t totalspace2 = totalspace / (1024 * 1024); + occupedspace = (usedspace2 * 100) / totalspace2; //minimum if even one byte is used is 1% - if ( occupedspace <= 1) { - occupedspace=1; + if (occupedspace <= 1) { + occupedspace = 1; } if (totalspace) { - jsonfile+= stotalspace ; + jsonfile += stotalspace; } else { - jsonfile+= "-1"; + jsonfile += "-1"; } - jsonfile+="\",\"used\":\""; - jsonfile+= susedspace ; - jsonfile+="\",\"occupation\":\""; + jsonfile += "\",\"used\":\""; + jsonfile += susedspace; + jsonfile += "\",\"occupation\":\""; if (totalspace) { - jsonfile+= String(occupedspace); + jsonfile += String(occupedspace); } else { - jsonfile+= "-1"; + jsonfile += "-1"; } - jsonfile+= "\","; - jsonfile+= "\"mode\":\"direct\","; - jsonfile+= "\"status\":\""; - jsonfile+=sstatus + "\""; - jsonfile+= "}"; - _webserver->sendHeader("Cache-Control","no-cache"); - _webserver->send (200, "application/json", jsonfile.c_str()); - _upload_status=UPLOAD_STATUS_NONE; + jsonfile += "\","; + jsonfile += "\"mode\":\"direct\","; + jsonfile += "\"status\":\""; + jsonfile += sstatus + "\""; + jsonfile += "}"; + _webserver->sendHeader("Cache-Control", "no-cache"); + _webserver->send(200, "application/json", jsonfile.c_str()); + _upload_status = UPLOAD_STATUS_NONE; set_sd_state(SDCARD_IDLE); } //SD File upload with direct access to SD/////////////////////////////// -void Web_Server::SDFile_direct_upload() -{ - static String filename ; - static File sdUploadFile; +void Web_Server::SDFile_direct_upload() { + static String filename; + static File sdUploadFile; //this is only for admin and user if (is_authenticated() == LEVEL_GUEST) { - _upload_status=UPLOAD_STATUS_FAILED; + _upload_status = UPLOAD_STATUS_FAILED; _webserver->send(401, "application/json", "{\"status\":\"Authentication failed!\"}"); pushError(ESP_ERROR_AUTHENTICATION, "Upload rejected", 401); } else { //retrieve current file id HTTPUpload& upload = _webserver->upload(); - if((_upload_status != UPLOAD_STATUS_FAILED)|| (upload.status == UPLOAD_FILE_START)){ + if ((_upload_status != UPLOAD_STATUS_FAILED) || (upload.status == UPLOAD_FILE_START)) { //Upload start //************** - if(upload.status == UPLOAD_FILE_START) { - _upload_status= UPLOAD_STATUS_ONGOING; - filename= upload.filename; + if (upload.status == UPLOAD_FILE_START) { + _upload_status = UPLOAD_STATUS_ONGOING; + filename = upload.filename; //on SD need to add / if not present - if (filename[0]!='/') { - filename= "/"+upload.filename; + if (filename[0] != '/') { + filename = "/" + upload.filename; } //check if SD Card is available - if ( get_sd_state(true) != SDCARD_IDLE) { - _upload_status=UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload cancelled]\r\n"); + if (get_sd_state(true) != SDCARD_IDLE) { + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Upload cancelled]\r\n"); pushError(ESP_ERROR_UPLOAD_CANCELLED, "Upload cancelled"); - + } else { set_sd_state(SDCARD_BUSY_UPLOADING); //delete file on SD Card if already present - if(SD.exists((char *)filename.c_str())) { - SD.remove((char *)filename.c_str()); + if (SD.exists((char*)filename.c_str())) { + SD.remove((char*)filename.c_str()); } - String sizeargname = upload.filename + "S"; - if (_webserver->hasArg (sizeargname.c_str()) ) { - uint32_t filesize = _webserver->arg (sizeargname.c_str()).toInt(); - uint64_t freespace = SD.totalBytes() - SD.usedBytes(); - if (filesize > freespace) { - _upload_status=UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload error]\r\n"); + String sizeargname = upload.filename + "S"; + if (_webserver->hasArg(sizeargname.c_str())) { + uint32_t filesize = _webserver->arg(sizeargname.c_str()).toInt(); + uint64_t freespace = SD.totalBytes() - SD.usedBytes(); + if (filesize > freespace) { + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Upload error]\r\n"); pushError(ESP_ERROR_NOT_ENOUGH_SPACE, "Upload rejected, not enough space"); - } - + } } - if (_upload_status != UPLOAD_STATUS_FAILED){ + if (_upload_status != UPLOAD_STATUS_FAILED) { //Create file for writing - sdUploadFile = SD.open((char *)filename.c_str(), FILE_WRITE); + sdUploadFile = SD.open((char*)filename.c_str(), FILE_WRITE); //check if creation succeed if (!sdUploadFile) { //if creation failed - _upload_status=UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload failed]\r\n"); + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Upload failed]\r\n"); pushError(ESP_ERROR_FILE_CREATION, "File creation failed"); } //if creation succeed set flag UPLOAD_STATUS_ONGOING else { - _upload_status= UPLOAD_STATUS_ONGOING; + _upload_status = UPLOAD_STATUS_ONGOING; } } } //Upload write //************** - } else if(upload.status == UPLOAD_FILE_WRITE) { + } else if (upload.status == UPLOAD_FILE_WRITE) { vTaskDelay(1 / portTICK_RATE_MS); - if(sdUploadFile && (_upload_status == UPLOAD_STATUS_ONGOING) && (get_sd_state(false) == SDCARD_BUSY_UPLOADING)) { + if (sdUploadFile && (_upload_status == UPLOAD_STATUS_ONGOING) && (get_sd_state(false) == SDCARD_BUSY_UPLOADING)) { //no error write post data if (upload.currentSize != sdUploadFile.write(upload.buf, upload.currentSize)) { - _upload_status = UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload failed]\r\n"); - pushError(ESP_ERROR_FILE_WRITE, "File write failed"); + _upload_status = UPLOAD_STATUS_FAILED; + grbl_send(CLIENT_ALL, "[MSG:Upload failed]\r\n"); + pushError(ESP_ERROR_FILE_WRITE, "File write failed"); } - } else { //if error set flag UPLOAD_STATUS_FAILED + } else { //if error set flag UPLOAD_STATUS_FAILED _upload_status = UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload failed]\r\n"); + grbl_send(CLIENT_ALL, "[MSG:Upload failed]\r\n"); pushError(ESP_ERROR_FILE_WRITE, "File write failed"); } //Upload end //************** - } else if(upload.status == UPLOAD_FILE_END) { + } else if (upload.status == UPLOAD_FILE_END) { //if file is open close it - if(sdUploadFile) { + if (sdUploadFile) { sdUploadFile.close(); //TODO Check size - String sizeargname = upload.filename + "S"; - if (_webserver->hasArg (sizeargname.c_str()) ) { + String sizeargname = upload.filename + "S"; + if (_webserver->hasArg(sizeargname.c_str())) { uint32_t filesize = 0; - sdUploadFile = SD.open (filename.c_str(), FILE_READ); - filesize = sdUploadFile.size(); + sdUploadFile = SD.open(filename.c_str(), FILE_READ); + filesize = sdUploadFile.size(); sdUploadFile.close(); - if (_webserver->arg (sizeargname.c_str()) != String(filesize)) { + if (_webserver->arg(sizeargname.c_str()) != String(filesize)) { _upload_status = UPLOAD_STATUS_FAILED; pushError(ESP_ERROR_UPLOAD, "File upload mismatch"); - grbl_send(CLIENT_ALL,"[MSG:Upload failed]\r\n"); - } + grbl_send(CLIENT_ALL, "[MSG:Upload failed]\r\n"); + } } } else { _upload_status = UPLOAD_STATUS_FAILED; - grbl_send(CLIENT_ALL,"[MSG:Upload failed]\r\n"); + grbl_send(CLIENT_ALL, "[MSG:Upload failed]\r\n"); pushError(ESP_ERROR_FILE_CLOSE, "File close failed"); } if (_upload_status == UPLOAD_STATUS_ONGOING) { @@ -1515,12 +1524,12 @@ void Web_Server::SDFile_direct_upload() _upload_status = UPLOAD_STATUS_FAILED; pushError(ESP_ERROR_UPLOAD, "Upload error"); } - - } else {//Upload cancelled - _upload_status=UPLOAD_STATUS_FAILED; + + } else { //Upload cancelled + _upload_status = UPLOAD_STATUS_FAILED; set_sd_state(SDCARD_IDLE); - grbl_send(CLIENT_ALL,"[MSG:Upload failed]\r\n"); - if(sdUploadFile) { + grbl_send(CLIENT_ALL, "[MSG:Upload failed]\r\n"); + if (sdUploadFile) { sdUploadFile.close(); } return; @@ -1529,58 +1538,55 @@ void Web_Server::SDFile_direct_upload() } if (_upload_status == UPLOAD_STATUS_FAILED) { cancelUpload(); - if(sdUploadFile) { + if (sdUploadFile) { sdUploadFile.close(); - } - if(SD.exists((char *)filename.c_str())) { - SD.remove((char *)filename.c_str()); - } + } + if (SD.exists((char*)filename.c_str())) { + SD.remove((char*)filename.c_str()); + } set_sd_state(SDCARD_IDLE); } COMMANDS::wait(0); } -#endif +# endif -void Web_Server::handle(){ -static uint32_t timeout = millis(); +void Web_Server::handle() { + static uint32_t timeout = millis(); COMMANDS::wait(0); -#ifdef ENABLE_CAPTIVE_PORTAL - if(WiFi.getMode() == WIFI_AP){ +# ifdef ENABLE_CAPTIVE_PORTAL + if (WiFi.getMode() == WIFI_AP) { dnsServer.processNextRequest(); } -#endif - if (_webserver)_webserver->handleClient(); - if (_socket_server && _setupdone)_socket_server->loop(); +# endif + if (_webserver) + _webserver->handleClient(); + if (_socket_server && _setupdone) + _socket_server->loop(); if ((millis() - timeout) > 10000) { - if (_socket_server){ - String s = "PING:"; - s+=String(_id_connection); + if (_socket_server) { + String s = "PING:"; + s += String(_id_connection); _socket_server->broadcastTXT(s); - timeout=millis(); + timeout = millis(); } } - } - -void Web_Server::handle_Websocket_Event(uint8_t num, uint8_t type, uint8_t * payload, size_t length) { - - switch(type) { +void Web_Server::handle_Websocket_Event(uint8_t num, uint8_t type, uint8_t* payload, size_t length) { + switch (type) { case WStype_DISCONNECTED: //USE_SERIAL.printf("[%u] Disconnected!\n", num); break; - case WStype_CONNECTED: - { - IPAddress ip = _socket_server->remoteIP(num); - //USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); - String s = "CURRENT_ID:" + String(num); - // send message to client - _id_connection = num; - _socket_server->sendTXT(_id_connection, s); - s = "ACTIVE_ID:" + String(_id_connection); - _socket_server->broadcastTXT(s); - } - break; + case WStype_CONNECTED: { + IPAddress ip = _socket_server->remoteIP(num); + //USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); + String s = "CURRENT_ID:" + String(num); + // send message to client + _id_connection = num; + _socket_server->sendTXT(_id_connection, s); + s = "ACTIVE_ID:" + String(_id_connection); + _socket_server->broadcastTXT(s); + } break; case WStype_TEXT: //USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); @@ -1597,134 +1603,133 @@ void Web_Server::handle_Websocket_Event(uint8_t num, uint8_t type, uint8_t * pay // send message to client // webSocket.sendBIN(num, payload, length); break; - default: - break; + default: break; } - } // The separator that is passed in to this function is always '\n' // The string that is returned does not contain the separator // The calling code adds back the separator, unless the string is // a one-character realtime command. -String Web_Server::get_Splited_Value(String data, char separator, int index) -{ - int found = 0; - int strIndex[] = {0, -1}; - int maxIndex = data.length()-1; +String Web_Server::get_Splited_Value(String data, char separator, int index) { + int found = 0; + int strIndex[] = { 0, -1 }; + int maxIndex = data.length() - 1; - for(int i=0; i<=maxIndex && found<=index; i++){ - if(data.charAt(i)==separator || i==maxIndex){ - found++; - strIndex[0] = strIndex[1]+1; - strIndex[1] = (i == maxIndex) ? i+1 : i; + for (int i = 0; i <= maxIndex && found <= index; i++) { + if (data.charAt(i) == separator || i == maxIndex) { + found++; + strIndex[0] = strIndex[1] + 1; + strIndex[1] = (i == maxIndex) ? i + 1 : i; + } } - } - return found>index ? data.substring(strIndex[0], strIndex[1]) : ""; + return found > index ? data.substring(strIndex[0], strIndex[1]) : ""; } - //helper to extract content type from file extension //Check what is the content tye according extension file -String Web_Server::getContentType (String filename) -{ +String Web_Server::getContentType(String filename) { String file_name = filename; file_name.toLowerCase(); - if (filename.endsWith (".htm") ) { + if (filename.endsWith(".htm")) { return "text/html"; - } else if (file_name.endsWith (".html") ) { + } else if (file_name.endsWith(".html")) { return "text/html"; - } else if (file_name.endsWith (".css") ) { + } else if (file_name.endsWith(".css")) { return "text/css"; - } else if (file_name.endsWith (".js") ) { + } else if (file_name.endsWith(".js")) { return "application/javascript"; - } else if (file_name.endsWith (".png") ) { + } else if (file_name.endsWith(".png")) { return "image/png"; - } else if (file_name.endsWith (".gif") ) { + } else if (file_name.endsWith(".gif")) { return "image/gif"; - } else if (file_name.endsWith (".jpeg") ) { + } else if (file_name.endsWith(".jpeg")) { return "image/jpeg"; - } else if (file_name.endsWith (".jpg") ) { + } else if (file_name.endsWith(".jpg")) { return "image/jpeg"; - } else if (file_name.endsWith (".ico") ) { + } else if (file_name.endsWith(".ico")) { return "image/x-icon"; - } else if (file_name.endsWith (".xml") ) { + } else if (file_name.endsWith(".xml")) { return "text/xml"; - } else if (file_name.endsWith (".pdf") ) { + } else if (file_name.endsWith(".pdf")) { return "application/x-pdf"; - } else if (file_name.endsWith (".zip") ) { + } else if (file_name.endsWith(".zip")) { return "application/x-zip"; - } else if (file_name.endsWith (".gz") ) { + } else if (file_name.endsWith(".gz")) { return "application/x-gzip"; - } else if (file_name.endsWith (".txt") ) { + } else if (file_name.endsWith(".txt")) { return "text/plain"; } return "application/octet-stream"; } //check authentification -auth_t Web_Server::is_authenticated() -{ -#ifdef ENABLE_AUTHENTICATION - if (_webserver->hasHeader ("Cookie") ) { - String cookie = _webserver->header ("Cookie"); - int pos = cookie.indexOf ("ESPSESSIONID="); +auth_t Web_Server::is_authenticated() { +# ifdef ENABLE_AUTHENTICATION + if (_webserver->hasHeader("Cookie")) { + String cookie = _webserver->header("Cookie"); + int pos = cookie.indexOf("ESPSESSIONID="); if (pos != -1) { - int pos2 = cookie.indexOf (";", pos); - String sessionID = cookie.substring (pos + strlen ("ESPSESSIONID="), pos2); - IPAddress ip = _webserver->client().remoteIP(); + int pos2 = cookie.indexOf(";", pos); + String sessionID = cookie.substring(pos + strlen("ESPSESSIONID="), pos2); + IPAddress ip = _webserver->client().remoteIP(); //check if cookie can be reset and clean table in same time - return ResetAuthIP (ip, sessionID.c_str() ); + return ResetAuthIP(ip, sessionID.c_str()); } } return LEVEL_GUEST; -#else +# else return LEVEL_ADMIN; -#endif +# endif } -#ifdef ENABLE_AUTHENTICATION +# ifdef ENABLE_AUTHENTICATION //add the information in the linked list if possible -bool Web_Server::AddAuthIP (auth_ip * item) -{ +bool Web_Server::AddAuthIP(auth_ip* item) { if (_nb_ip > MAX_AUTH_IP) { return false; } item->_next = _head; - _head = item; + _head = item; _nb_ip++; return true; } //Session ID based on IP and time using 16 char -char * Web_Server::create_session_ID() -{ - static char sessionID[17]; -//reset SESSIONID +char* Web_Server::create_session_ID() { + static char sessionID[17]; + //reset SESSIONID for (int i = 0; i < 17; i++) { sessionID[i] = '\0'; } -//get time + //get time uint32_t now = millis(); -//get remote IP + //get remote IP IPAddress remoteIP = _webserver->client().remoteIP(); -//generate SESSIONID - if (0 > sprintf (sessionID, "%02X%02X%02X%02X%02X%02X%02X%02X", remoteIP[0], remoteIP[1], remoteIP[2], remoteIP[3], (uint8_t) ( (now >> 0) & 0xff), (uint8_t) ( (now >> 8) & 0xff), (uint8_t) ( (now >> 16) & 0xff), (uint8_t) ( (now >> 24) & 0xff) ) ) { - strcpy (sessionID, "NONE"); + //generate SESSIONID + if (0 > sprintf(sessionID, + "%02X%02X%02X%02X%02X%02X%02X%02X", + remoteIP[0], + remoteIP[1], + remoteIP[2], + remoteIP[3], + (uint8_t)((now >> 0) & 0xff), + (uint8_t)((now >> 8) & 0xff), + (uint8_t)((now >> 16) & 0xff), + (uint8_t)((now >> 24) & 0xff))) { + strcpy(sessionID, "NONE"); } return sessionID; } - -bool Web_Server::ClearAuthIP (IPAddress ip, const char * sessionID) -{ - auth_ip * current = _head; - auth_ip * previous = NULL; - bool done = false; +bool Web_Server::ClearAuthIP(IPAddress ip, const char* sessionID) { + auth_ip* current = _head; + auth_ip* previous = NULL; + bool done = false; while (current) { - if ( (ip == current->ip) && (strcmp (sessionID, current->sessionID) == 0) ) { + if ((ip == current->ip) && (strcmp(sessionID, current->sessionID) == 0)) { //remove done = true; if (current == _head) { @@ -1740,22 +1745,21 @@ bool Web_Server::ClearAuthIP (IPAddress ip, const char * sessionID) } } else { previous = current; - current = current->_next; + current = current->_next; } } return done; } //Get info -auth_ip * Web_Server::GetAuth (IPAddress ip, const char * sessionID) -{ - auth_ip * current = _head; +auth_ip* Web_Server::GetAuth(IPAddress ip, const char* sessionID) { + auth_ip* current = _head; //auth_ip * previous = NULL; //get time //uint32_t now = millis(); while (current) { if (ip == current->ip) { - if (strcmp (sessionID, current->sessionID) == 0) { + if (strcmp(sessionID, current->sessionID) == 0) { //found return current; } @@ -1767,14 +1771,13 @@ auth_ip * Web_Server::GetAuth (IPAddress ip, const char * sessionID) } //Review all IP to reset timers -auth_t Web_Server::ResetAuthIP (IPAddress ip, const char * sessionID) -{ - auth_ip * current = _head; - auth_ip * previous = NULL; +auth_t Web_Server::ResetAuthIP(IPAddress ip, const char* sessionID) { + auth_ip* current = _head; + auth_ip* previous = NULL; //get time //uint32_t now = millis(); while (current) { - if ( (millis() - current->last_time) > 360000) { + if ((millis() - current->last_time) > 360000) { //remove if (current == _head) { _head = current->_next; @@ -1789,20 +1792,18 @@ auth_t Web_Server::ResetAuthIP (IPAddress ip, const char * sessionID) } } else { if (ip == current->ip) { - if (strcmp (sessionID, current->sessionID) == 0) { + if (strcmp(sessionID, current->sessionID) == 0) { //reset time current->last_time = millis(); - return (auth_t) current->level; + return (auth_t)current->level; } } previous = current; - current = current->_next; + current = current->_next; } } return LEVEL_GUEST; } -#endif +# endif -#endif // Enable HTTP && ENABLE_WIFI - -#endif // ARDUINO_ARCH_ESP32 +#endif // Enable HTTP && ENABLE_WIFI diff --git a/Grbl_Esp32/web_server.h b/Grbl_Esp32/web_server.h index bcd58bd7..97514c43 100644 --- a/Grbl_Esp32/web_server.h +++ b/Grbl_Esp32/web_server.h @@ -28,41 +28,42 @@ class WebServer; #ifdef ENABLE_AUTHENTICATION struct auth_ip { IPAddress ip; - auth_t level; - char userID[17]; - char sessionID[17]; - uint32_t last_time; - auth_ip* _next; + auth_t level; + char userID[17]; + char sessionID[17]; + uint32_t last_time; + auth_ip* _next; }; #endif class Web_Server { - public: +public: Web_Server(); ~Web_Server(); - bool begin(); - void end(); - void handle(); - static long get_client_ID(); - static uint16_t port() {return _port;} - private: - static bool _setupdone; - static WebServer* _webserver; - static long _id_connection; + bool begin(); + void end(); + void handle(); + static long get_client_ID(); + static uint16_t port() { return _port; } + +private: + static bool _setupdone; + static WebServer* _webserver; + static long _id_connection; static WebSocketsServer* _socket_server; - static uint16_t _port; - static uint8_t _upload_status; - static String getContentType(String filename); - static String get_Splited_Value(String data, char separator, int index); - static auth_t is_authenticated(); + static uint16_t _port; + static uint8_t _upload_status; + static String getContentType(String filename); + static String get_Splited_Value(String data, char separator, int index); + static auth_t is_authenticated(); #ifdef ENABLE_AUTHENTICATION static auth_ip* _head; - static uint8_t _nb_ip; - static bool AddAuthIP(auth_ip* item); - static char* create_session_ID(); - static bool ClearAuthIP(IPAddress ip, const char* sessionID); + static uint8_t _nb_ip; + static bool AddAuthIP(auth_ip* item); + static char* create_session_ID(); + static bool ClearAuthIP(IPAddress ip, const char* sessionID); static auth_ip* GetAuth(IPAddress ip, const char* sessionID); - static auth_t ResetAuthIP(IPAddress ip, const char* sessionID); + static auth_t ResetAuthIP(IPAddress ip, const char* sessionID); #endif #ifdef ENABLE_SSDP static void handle_SSDP(); @@ -79,7 +80,7 @@ class Web_Server { static void handleUpdate(); static void WebUpdateUpload(); static bool is_realtime_cmd(char c); - static void pushError(int code, const char* st, bool web_error = 500, uint16_t timeout = 1000); + static void pushError(int code, const char* st, bool web_error = 500, uint16_t timeout = 1000); static void cancelUpload(); #ifdef ENABLE_SD_CARD static void handle_direct_SDFileList(); diff --git a/Grbl_Esp32/wificonfig.cpp b/Grbl_Esp32/wificonfig.cpp index 80857f7f..f34fda77 100644 --- a/Grbl_Esp32/wificonfig.cpp +++ b/Grbl_Esp32/wificonfig.cpp @@ -18,34 +18,30 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef ARDUINO_ARCH_ESP32 - #include "grbl.h" #ifdef ENABLE_WIFI -#include -#include -#include -#include -#include -#include "wifiservices.h" - +# include +# include +# include +# include +# include +# include "wifiservices.h" WiFiConfig wifi_config; -String WiFiConfig::_hostname = ""; -bool WiFiConfig::_events_registered = false; -WiFiConfig::WiFiConfig() { -} +String WiFiConfig::_hostname = ""; +bool WiFiConfig::_events_registered = false; +WiFiConfig::WiFiConfig() {} WiFiConfig::~WiFiConfig() { end(); } //just simple helper to convert mac address to string -char* WiFiConfig::mac2str(uint8_t mac [8]) { - static char macstr [18]; +char* WiFiConfig::mac2str(uint8_t mac[8]) { + static char macstr[18]; if (0 > sprintf(macstr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])) strcpy(macstr, "00:00:00:00:00:00"); return macstr; @@ -53,7 +49,7 @@ char* WiFiConfig::mac2str(uint8_t mac [8]) { const char* WiFiConfig::info() { static String result; - String tmp; + String tmp; result = "[MSG:"; if ((WiFi.getMode() == WIFI_MODE_STA) || (WiFi.getMode() == WIFI_MODE_APSTA)) { result += "Mode=STA:SSID="; @@ -81,7 +77,8 @@ const char* WiFiConfig::info() { tmp.replace(":", "-"); result += tmp; } - if (WiFi.getMode() == WIFI_MODE_NULL)result += "No Wifi"; + if (WiFi.getMode() == WIFI_MODE_NULL) + result += "No Wifi"; result += "]\r\n"; return result.c_str(); } @@ -91,9 +88,10 @@ const char* WiFiConfig::info() { */ uint32_t WiFiConfig::IP_int_from_string(String& s) { - uint32_t ip_int = 0; + uint32_t ip_int = 0; IPAddress ipaddr; - if (ipaddr.fromString(s)) ip_int = ipaddr; + if (ipaddr.fromString(s)) + ip_int = ipaddr; return ip_int; } @@ -125,7 +123,6 @@ bool WiFiConfig::isHostnameValid(const char* hostname) { return true; } - /** * Check if SSID string is valid */ @@ -147,7 +144,8 @@ bool WiFiConfig::isSSIDValid(const char* ssid) { */ bool WiFiConfig::isPasswordValid(const char* password) { - if (strlen(password) == 0) return true; //open network + if (strlen(password) == 0) + return true; //open network //limited size // length is checked automatically by string setting //no space allowed ? @@ -166,7 +164,6 @@ bool WiFiConfig::isValidIP(const char* string) { return ip.fromString(string); } - /** * WiFi events * SYSTEM_EVENT_WIFI_READY < ESP32 WiFi ready @@ -198,14 +195,9 @@ bool WiFiConfig::isValidIP(const char* string) { void WiFiConfig::WiFiEvent(WiFiEvent_t event) { switch (event) { - case SYSTEM_EVENT_STA_GOT_IP: - grbl_sendf(CLIENT_ALL, "[MSG:Connected with %s]\r\n", WiFi.localIP().toString().c_str()); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - grbl_send(CLIENT_ALL, "[MSG:Disconnected]\r\n"); - break; - default: - break; + case SYSTEM_EVENT_STA_GOT_IP: grbl_sendf(CLIENT_ALL, "[MSG:Connected with %s]\r\n", WiFi.localIP().toString().c_str()); break; + case SYSTEM_EVENT_STA_DISCONNECTED: grbl_send(CLIENT_ALL, "[MSG:Disconnected]\r\n"); break; + default: break; } } @@ -225,29 +217,24 @@ int32_t WiFiConfig::getSignal(int32_t RSSI) { */ bool WiFiConfig::ConnectSTA2AP() { - String msg, msg_out; - uint8_t count = 0; - uint8_t dot = 0; + String msg, msg_out; + uint8_t count = 0; + uint8_t dot = 0; wl_status_t status = WiFi.status(); while (status != WL_CONNECTED && count < 40) { switch (status) { - case WL_NO_SSID_AVAIL: - msg = "No SSID"; - break; - case WL_CONNECT_FAILED: - msg = "Connection failed"; - break; - case WL_CONNECTED: - break; - default: - if ((dot > 3) || (dot == 0)) { - dot = 0; - msg_out = "Connecting"; - } - msg_out += "."; - msg = msg_out; - dot++; - break; + case WL_NO_SSID_AVAIL: msg = "No SSID"; break; + case WL_CONNECT_FAILED: msg = "Connection failed"; break; + case WL_CONNECTED: break; + default: + if ((dot > 3) || (dot == 0)) { + dot = 0; + msg_out = "Connecting"; + } + msg_out += "."; + msg = msg_out; + dot++; + break; } grbl_sendf(CLIENT_ALL, "[MSG:%s]\r\n", msg.c_str()); COMMANDS::wait(500); @@ -265,8 +252,10 @@ bool WiFiConfig::StartSTA() { //stop active service wifi_services.end(); //Sanity check - if ((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA))WiFi.disconnect(); - if ((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA))WiFi.softAPdisconnect(); + if ((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) + WiFi.disconnect(); + if ((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) + WiFi.softAPdisconnect(); WiFi.enableAP(false); WiFi.mode(WIFI_STA); //Get parameters for STA @@ -274,13 +263,14 @@ bool WiFiConfig::StartSTA() { WiFi.setHostname(h.c_str()); //SSID String SSID = wifi_sta_ssid->get(); - if (SSID.length() == 0) SSID = DEFAULT_STA_SSID; + if (SSID.length() == 0) + SSID = DEFAULT_STA_SSID; //password - String password = wifi_sta_password->get(); - int8_t IP_mode = wifi_sta_mode->get(); - int32_t IP = wifi_sta_ip->get(); - int32_t GW = wifi_sta_gateway->get(); - int32_t MK = wifi_sta_netmask->get(); + String password = wifi_sta_password->get(); + int8_t IP_mode = wifi_sta_mode->get(); + int32_t IP = wifi_sta_ip->get(); + int32_t GW = wifi_sta_gateway->get(); + int32_t MK = wifi_sta_netmask->get(); //if not DHCP if (IP_mode != DHCP_MODE) { IPAddress ip(IP), mask(MK), gateway(GW); @@ -304,21 +294,25 @@ bool WiFiConfig::StartAP() { //stop active services wifi_services.end(); //Sanity check - if ((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA))WiFi.disconnect(); - if ((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA))WiFi.softAPdisconnect(); + if ((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) + WiFi.disconnect(); + if ((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) + WiFi.softAPdisconnect(); WiFi.enableSTA(false); WiFi.mode(WIFI_AP); //Get parameters for AP //SSID String SSID = wifi_ap_ssid->get(); - if (SSID.length() == 0) SSID = DEFAULT_AP_SSID; + if (SSID.length() == 0) + SSID = DEFAULT_AP_SSID; String password = wifi_ap_password->get(); int8_t channel = wifi_ap_channel->get(); - if (channel == 0) channel = DEFAULT_AP_CHANNEL; + if (channel == 0) + channel = DEFAULT_AP_CHANNEL; - int32_t IP = wifi_ap_ip->get(); + int32_t IP = wifi_ap_ip->get(); IPAddress ip(IP); IPAddress mask; mask.fromString(DEFAULT_AP_MK); @@ -340,8 +334,10 @@ bool WiFiConfig::StartAP() { void WiFiConfig::StopWiFi() { //Sanity check - if ((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA))WiFi.disconnect(true); - if ((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA))WiFi.softAPdisconnect(true); + if ((WiFi.getMode() == WIFI_STA) || (WiFi.getMode() == WIFI_AP_STA)) + WiFi.disconnect(true); + if ((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) + WiFi.softAPdisconnect(true); wifi_services.end(); WiFi.enableSTA(false); WiFi.enableAP(false); @@ -362,7 +358,7 @@ void WiFiConfig::begin() { _events_registered = true; } //Get hostname - _hostname = wifi_hostname->get(); + _hostname = wifi_hostname->get(); int8_t wifiMode = wifi_radio_mode->get(); if (wifiMode == ESP_WIFI_AP) { StartAP(); @@ -375,7 +371,8 @@ void WiFiConfig::begin() { } //start services wifi_services.begin(); - } else WiFi.mode(WIFI_OFF); + } else + WiFi.mode(WIFI_OFF); } /** @@ -390,12 +387,12 @@ void WiFiConfig::end() { */ void WiFiConfig::reset_settings() { bool error = false; - for (Setting *s = Setting::List; s; s = s->next()) { + for (Setting* s = Setting::List; s; s = s->next()) { if (s->getDescription()) { s->setDefault(); } - } - // TODO commit the changes and check that for errors + } + // TODO commit the changes and check that for errors if (error) grbl_send(CLIENT_ALL, "[MSG:WiFi reset error]\r\n"); grbl_send(CLIENT_ALL, "[MSG:WiFi reset done]\r\n"); @@ -413,7 +410,4 @@ void WiFiConfig::handle() { wifi_services.handle(); } - -#endif // ENABLE_WIFI - -#endif // ARDUINO_ARCH_ESP32 +#endif // ENABLE_WIFI diff --git a/Grbl_Esp32/wificonfig.h b/Grbl_Esp32/wificonfig.h index 799fd020..ea750ea9 100644 --- a/Grbl_Esp32/wificonfig.h +++ b/Grbl_Esp32/wificonfig.h @@ -23,12 +23,12 @@ //Preferences entries //Notifications -#define ESP_PUSHOVER_NOTIFICATION 1 -#define ESP_EMAIL_NOTIFICATION 2 -#define ESP_LINE_NOTIFICATION 3 +#define ESP_PUSHOVER_NOTIFICATION 1 +#define ESP_EMAIL_NOTIFICATION 2 +#define ESP_LINE_NOTIFICATION 3 -#define DHCP_MODE 0 -#define STATIC_MODE 1 +#define DHCP_MODE 0 +#define STATIC_MODE 1 //Switch #define ESP_SAVE_ONLY 0 @@ -37,12 +37,12 @@ //defaults values #define DEFAULT_HOSTNAME "grblesp" #ifdef CONNECT_TO_SSID - #define DEFAULT_STA_SSID CONNECT_TO_SSID - #define DEFAULT_STA_PWD SSID_PASSWORD -#else //!CONNECT_TO_SSID - #define DEFAULT_STA_SSID "GRBL_ESP" - #define DEFAULT_STA_PWD "12345678" -#endif //CONNECT_TO_SSID +# define DEFAULT_STA_SSID CONNECT_TO_SSID +# define DEFAULT_STA_PWD SSID_PASSWORD +#else //!CONNECT_TO_SSID +# define DEFAULT_STA_SSID "GRBL_ESP" +# define DEFAULT_STA_PWD "12345678" +#endif //CONNECT_TO_SSID #define DEFAULT_STA_IP "0.0.0.0" #define DEFAULT_STA_GW "0.0.0.0" #define DEFAULT_STA_MK "0.0.0.0" @@ -61,53 +61,54 @@ #define DEFAULT_NOTIFICATION_TYPE 0 //boundaries -#define MAX_SSID_LENGTH 32 -#define MIN_SSID_LENGTH 1 -#define MAX_PASSWORD_LENGTH 64 +#define MAX_SSID_LENGTH 32 +#define MIN_SSID_LENGTH 1 +#define MAX_PASSWORD_LENGTH 64 //min size of password is 0 or upper than 8 char //so let set min is 8 -#define MIN_PASSWORD_LENGTH 8 -#define MAX_HOSTNAME_LENGTH 32 -#define MIN_HOSTNAME_LENGTH 1 -#define MAX_HTTP_PORT 65001 -#define MIN_HTTP_PORT 1 -#define MAX_TELNET_PORT 65001 -#define MIN_TELNET_PORT 1 -#define MIN_CHANNEL 1 -#define MAX_CHANNEL 14 -#define MIN_NOTIFICATION_TOKEN_LENGTH 0 -#define MAX_NOTIFICATION_TOKEN_LENGTH 63 -#define MAX_NOTIFICATION_SETTING_LENGTH 127 +#define MIN_PASSWORD_LENGTH 8 +#define MAX_HOSTNAME_LENGTH 32 +#define MIN_HOSTNAME_LENGTH 1 +#define MAX_HTTP_PORT 65001 +#define MIN_HTTP_PORT 1 +#define MAX_TELNET_PORT 65001 +#define MIN_TELNET_PORT 1 +#define MIN_CHANNEL 1 +#define MAX_CHANNEL 14 +#define MIN_NOTIFICATION_TOKEN_LENGTH 0 +#define MAX_NOTIFICATION_TOKEN_LENGTH 63 +#define MAX_NOTIFICATION_SETTING_LENGTH 127 #include "WiFi.h" class WiFiConfig { - public: +public: WiFiConfig(); ~WiFiConfig(); static const char* info(); - static bool isValidIP(const char* string); - static bool isPasswordValid(const char* password); - static bool isSSIDValid(const char* ssid); - static bool isHostnameValid(const char* hostname); - static uint32_t IP_int_from_string(String& s); - static String IP_string_from_int(uint32_t ip_int); - static String Hostname() {return _hostname;} - static char* mac2str(uint8_t mac [8]); - static bool StartAP(); - static bool StartSTA(); - static void StopWiFi(); - static int32_t getSignal(int32_t RSSI); - static void begin(); - static void end(); - static void handle(); - static void reset_settings(); - static bool Is_WiFi_on(); - private : - static bool ConnectSTA2AP(); - static void WiFiEvent(WiFiEvent_t event); + static bool isValidIP(const char* string); + static bool isPasswordValid(const char* password); + static bool isSSIDValid(const char* ssid); + static bool isHostnameValid(const char* hostname); + static uint32_t IP_int_from_string(String& s); + static String IP_string_from_int(uint32_t ip_int); + static String Hostname() { return _hostname; } + static char* mac2str(uint8_t mac[8]); + static bool StartAP(); + static bool StartSTA(); + static void StopWiFi(); + static int32_t getSignal(int32_t RSSI); + static void begin(); + static void end(); + static void handle(); + static void reset_settings(); + static bool Is_WiFi_on(); + +private: + static bool ConnectSTA2AP(); + static void WiFiEvent(WiFiEvent_t event); static String _hostname; - static bool _events_registered; + static bool _events_registered; }; extern WiFiConfig wifi_config; diff --git a/Grbl_Esp32/wifiservices.cpp b/Grbl_Esp32/wifiservices.cpp index fcc52d34..eff9e434 100644 --- a/Grbl_Esp32/wifiservices.cpp +++ b/Grbl_Esp32/wifiservices.cpp @@ -18,37 +18,34 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef ARDUINO_ARCH_ESP32 - #include "grbl.h" #ifdef ENABLE_WIFI -#include -#include -#include -#include "wifiservices.h" -#ifdef ENABLE_MDNS - #include -#endif -#ifdef ENABLE_OTA - #include -#endif -#ifdef ENABLE_HTTP - #include "web_server.h" -#endif -#ifdef ENABLE_TELNET - #include "telnet_server.h" -#endif -#ifdef ENABLE_NOTIFICATIONS - #include "notifications_service.h" -#endif -#include "commands.h" +# include +# include +# include +# include "wifiservices.h" +# ifdef ENABLE_MDNS +# include +# endif +# ifdef ENABLE_OTA +# include +# endif +# ifdef ENABLE_HTTP +# include "web_server.h" +# endif +# ifdef ENABLE_TELNET +# include "telnet_server.h" +# endif +# ifdef ENABLE_NOTIFICATIONS +# include "notifications_service.h" +# endif +# include "commands.h" WiFiServices wifi_services; -WiFiServices::WiFiServices() { -} +WiFiServices::WiFiServices() {} WiFiServices::~WiFiServices() { end(); } @@ -56,41 +53,45 @@ WiFiServices::~WiFiServices() { bool WiFiServices::begin() { bool no_error = true; //Sanity check - if (WiFi.getMode() == WIFI_OFF) return false; + if (WiFi.getMode() == WIFI_OFF) + return false; String h = wifi_hostname->get(); //Start SPIFFS SPIFFS.begin(true); -#ifdef ENABLE_OTA +# ifdef ENABLE_OTA ArduinoOTA - .onStart([]() { - String type; - if (ArduinoOTA.getCommand() == U_FLASH) - type = "sketch"; - else {// U_SPIFFS - // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() - type = "filesystem"; - SPIFFS.end(); - } - grbl_sendf(CLIENT_ALL, "[MSG:Start OTA updating %s]\r\n", type.c_str()); - }) - .onEnd([]() { - grbl_sendf(CLIENT_ALL, "[MSG:End OTA]\r\n"); - }) - .onProgress([](unsigned int progress, unsigned int total) { - grbl_sendf(CLIENT_ALL, "[MSG:OTA Progress: %u%%]\r\n", (progress / (total / 100))); - }) - .onError([](ota_error_t error) { - grbl_sendf(CLIENT_ALL, "[MSG:OTA Error(%u):]\r\n", error); - if (error == OTA_AUTH_ERROR) grbl_send(CLIENT_ALL, "[MSG:Auth Failed]\r\n"); - else if (error == OTA_BEGIN_ERROR) grbl_send(CLIENT_ALL, "[MSG:Begin Failed]\r\n"); - else if (error == OTA_CONNECT_ERROR) grbl_send(CLIENT_ALL, "[MSG:Connect Failed]\r\n"); - else if (error == OTA_RECEIVE_ERROR) grbl_send(CLIENT_ALL, "[MSG:Receive Failed]\r\n"); - else if (error == OTA_END_ERROR) grbl_send(CLIENT_ALL, "[MSG:End Failed]\r\n"); - }); + .onStart([]() { + String type; + if (ArduinoOTA.getCommand() == U_FLASH) + type = "sketch"; + else { // U_SPIFFS + // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() + type = "filesystem"; + SPIFFS.end(); + } + grbl_sendf(CLIENT_ALL, "[MSG:Start OTA updating %s]\r\n", type.c_str()); + }) + .onEnd([]() { grbl_sendf(CLIENT_ALL, "[MSG:End OTA]\r\n"); }) + .onProgress([](unsigned int progress, unsigned int total) { + grbl_sendf(CLIENT_ALL, "[MSG:OTA Progress: %u%%]\r\n", (progress / (total / 100))); + }) + .onError([](ota_error_t error) { + grbl_sendf(CLIENT_ALL, "[MSG:OTA Error(%u):]\r\n", error); + if (error == OTA_AUTH_ERROR) + grbl_send(CLIENT_ALL, "[MSG:Auth Failed]\r\n"); + else if (error == OTA_BEGIN_ERROR) + grbl_send(CLIENT_ALL, "[MSG:Begin Failed]\r\n"); + else if (error == OTA_CONNECT_ERROR) + grbl_send(CLIENT_ALL, "[MSG:Connect Failed]\r\n"); + else if (error == OTA_RECEIVE_ERROR) + grbl_send(CLIENT_ALL, "[MSG:Receive Failed]\r\n"); + else if (error == OTA_END_ERROR) + grbl_send(CLIENT_ALL, "[MSG:End Failed]\r\n"); + }); ArduinoOTA.begin(); -#endif -#ifdef ENABLE_MDNS +# endif +# ifdef ENABLE_MDNS //no need in AP mode if (WiFi.getMode() == WIFI_STA) { //start mDns @@ -100,40 +101,40 @@ bool WiFiServices::begin() { } else grbl_sendf(CLIENT_ALL, "[MSG:Start mDNS with hostname:http://%s.local/]\r\n", h.c_str()); } -#endif -#ifdef ENABLE_HTTP +# endif +# ifdef ENABLE_HTTP web_server.begin(); -#endif -#ifdef ENABLE_TELNET +# endif +# ifdef ENABLE_TELNET telnet_server.begin(); -#endif -#ifdef ENABLE_NOTIFICATIONS +# endif +# ifdef ENABLE_NOTIFICATIONS notificationsservice.begin(); -#endif +# endif //be sure we are not is mixed mode in setup WiFi.scanNetworks(true); return no_error; } void WiFiServices::end() { -#ifdef ENABLE_NOTIFICATIONS +# ifdef ENABLE_NOTIFICATIONS notificationsservice.end(); -#endif -#ifdef ENABLE_TELNET +# endif +# ifdef ENABLE_TELNET telnet_server.end(); -#endif -#ifdef ENABLE_HTTP +# endif +# ifdef ENABLE_HTTP web_server.end(); -#endif +# endif //stop OTA -#ifdef ENABLE_OTA +# ifdef ENABLE_OTA ArduinoOTA.end(); -#endif +# endif //Stop SPIFFS SPIFFS.end(); -#ifdef ENABLE_MDNS +# ifdef ENABLE_MDNS //Stop mDNS MDNS.end(); -#endif +# endif } void WiFiServices::handle() { @@ -147,17 +148,15 @@ void WiFiServices::handle() { WiFi.enableSTA(false); } } -#ifdef ENABLE_OTA +# ifdef ENABLE_OTA ArduinoOTA.handle(); -#endif -#ifdef ENABLE_HTTP +# endif +# ifdef ENABLE_HTTP web_server.handle(); -#endif -#ifdef ENABLE_TELNET +# endif +# ifdef ENABLE_TELNET telnet_server.handle(); -#endif +# endif } -#endif // ENABLE_WIFI - -#endif // ARDUINO_ARCH_ESP32 +#endif // ENABLE_WIFI diff --git a/Grbl_Esp32/wifiservices.h b/Grbl_Esp32/wifiservices.h index 4b98e326..b8185c40 100644 --- a/Grbl_Esp32/wifiservices.h +++ b/Grbl_Esp32/wifiservices.h @@ -21,7 +21,7 @@ */ class WiFiServices { - public: +public: WiFiServices(); ~WiFiServices(); static bool begin();