[
  {
    "path": "README.md",
    "content": "# grbl-servo\ngrbl 0.9i with Servo motor support\n\nGRBL 0.9i with servo motor support.\nUse the PIN D11 to drive the servo. \nUse the commands M03 Sxxx (xxx between 0 and 255) to rotate the servo between 0-180.\nThe command M05 turn the servo to zero degrees.\n\nyou can change the pulse duration in the file spindle_control.c:\n\ndefine RC_SERVO_SHORT     15       // Timer ticks for 0.6ms pulse duration  (9 for 0.6ms)\n\ndefine RC_SERVO_LONG      32       // Timer ticks for 2.5 ms pulse duration  (39 for 2.5ms)     \n\ndefine RC_SERVO_INVERT     1     // Uncomment to invert servo direction\n\nIf you want to have the servo working from 0 --> 180 degrees change RC_SERVO_SHORT and put 9, RC_SERVO_LONG and put 39\nIf you want invert the servo direction uncomment the line above.\n\nI tested the code very well with 328p (Arduino Uno, Duemilanove etv), not with 2560 (Arduino Mega), but I think it would work well also with the Mega.\n\n-------------------------------------------------------------------\n\nThe link for GRBL vanilla is: http://github.com/grbl/grbl\n\nGrbl is a no-compromise, high performance, low cost alternative to parallel-port-based motion control for CNC milling. It will run on a vanilla Arduino (Duemillanove/Uno) as long as it sports an Atmega 328.\n\nThe controller is written in highly optimized C utilizing every clever feature of the AVR-chips to achieve precise timing and asynchronous operation. It is able to maintain up to 30kHz of stable, jitter free control pulses.\n\nIt accepts standards-compliant g-code and has been tested with the output of several CAM tools with no problems. Arcs, circles and helical motion are fully supported, as well as, all other primary g-code commands. Macro functions, variables, and most canned cycles are not supported, but we think GUIs can do a much better job at translating them into straight g-code anyhow.\n\nGrbl includes full acceleration management with look ahead. That means the controller will look up to 18 motions into the future and plan its velocities ahead to deliver smooth acceleration and jerk-free cornering.\n\nLicensing: Grbl is free software, released under the GPLv3 license.\n\nFor more information and help, check out our Wiki pages! If you find that the information is out-dated, please to help us keep it updated by editing it or notifying our community! Thanks!\n\nLead Developer [2011 - Current]: Sungeun(Sonny) K. Jeon, Ph.D. (USA) aka @chamnit\n\nLead Developer [2009 - 2011]: Simen Svale Skogsrud (Norway). aka The Originator/Creator/Pioneer/Father of Grbl.\n\nThe link for GRBL vanilla is: http://github.com/grbl/grbl\n"
  },
  {
    "path": "config.h",
    "content": "/*\n  config.h - compile time configuration\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n  \n// This file contains compile-time configurations for Grbl's internal system. For the most part,\n// users will not need to directly modify these, but they are here for specific needs, i.e.\n// performance tuning or adjusting to non-typical machines.\n\n// IMPORTANT: Any changes here requires a full re-compiling of the source code to propagate them.\n\n#ifndef config_h\n#define config_h\n#include \"grbl.h\" // For Arduino IDE compatibility.\n\n\n// Default settings. Used when resetting EEPROM. Change to desired name in defaults.h\n#define DEFAULTS_GENERIC\n\n// Serial baud rate\n#define BAUD_RATE 115200\n\n// Default cpu mappings. Grbl officially supports the Arduino Uno only. Other processor types\n// may exist from user-supplied templates or directly user-defined in cpu_map.h\n#define CPU_MAP_ATMEGA328P // Arduino Uno CPU\n\n// Define realtime command special characters. These characters are 'picked-off' directly from the\n// serial read data stream and are not passed to the grbl line execution parser. Select characters\n// that do not and must not exist in the streamed g-code program. ASCII control characters may be \n// used, if they are available per user setup. Also, extended ASCII codes (>127), which are never in \n// g-code programs, maybe selected for interface programs.\n// NOTE: If changed, manually update help message in report.c.\n#define CMD_STATUS_REPORT '?'\n#define CMD_FEED_HOLD '!'\n#define CMD_CYCLE_START '~'\n#define CMD_RESET 0x18 // ctrl-x.\n#define CMD_SAFETY_DOOR '@'\n\n// If homing is enabled, homing init lock sets Grbl into an alarm state upon power up. This forces\n// the user to perform the homing cycle (or override the locks) before doing anything else. This is\n// mainly a safety feature to remind the user to home, since position is unknown to Grbl.\n#define HOMING_INIT_LOCK // Comment to disable\n\n// Define the homing cycle patterns with bitmasks. The homing cycle first performs a search mode\n// to quickly engage the limit switches, followed by a slower locate mode, and finished by a short\n// pull-off motion to disengage the limit switches. The following HOMING_CYCLE_x defines are executed \n// in order starting with suffix 0 and completes the homing routine for the specified-axes only. If\n// an axis is omitted from the defines, it will not home, nor will the system update its position.\n// Meaning that this allows for users with non-standard cartesian machines, such as a lathe (x then z,\n// with no y), to configure the homing cycle behavior to their needs. \n// NOTE: The homing cycle is designed to allow sharing of limit pins, if the axes are not in the same\n// cycle, but this requires some pin settings changes in cpu_map.h file. For example, the default homing\n// cycle can share the Z limit pin with either X or Y limit pins, since they are on different cycles.\n// By sharing a pin, this frees up a precious IO pin for other purposes. In theory, all axes limit pins\n// may be reduced to one pin, if all axes are homed with seperate cycles, or vice versa, all three axes\n// on separate pin, but homed in one cycle. Also, it should be noted that the function of hard limits \n// will not be affected by pin sharing.\n// NOTE: Defaults are set for a traditional 3-axis CNC machine. Z-axis first to clear, followed by X & Y.\n//#define HOMING_CYCLE_0 (1<<Z_AXIS)                // REQUIRED: First move Z to clear workspace.\n//#define HOMING_CYCLE_1 ((1<<X_AXIS)|(1<<Y_AXIS))  // OPTIONAL: Then move X,Y at the same time.\n#define HOMING_CYCLE_0 ((1<<X_AXIS)|(1<<Y_AXIS))\n// #define HOMING_CYCLE_2                         // OPTIONAL: Uncomment and add axes mask to enable\n\n// Number of homing cycles performed after when the machine initially jogs to limit switches.\n// This help in preventing overshoot and should improve repeatability. This value should be one or \n// greater.\n#define N_HOMING_LOCATE_CYCLE 1 // Integer (1-128)\n\n// After homing, Grbl will set by default the entire machine space into negative space, as is typical\n// for professional CNC machines, regardless of where the limit switches are located. Uncomment this \n// define to force Grbl to always set the machine origin at the homed location despite switch orientation.\n// #define HOMING_FORCE_SET_ORIGIN // Uncomment to enable.\n\n// Number of blocks Grbl executes upon startup. These blocks are stored in EEPROM, where the size\n// and addresses are defined in settings.h. With the current settings, up to 2 startup blocks may\n// be stored and executed in order. These startup blocks would typically be used to set the g-code\n// parser state depending on user preferences.\n#define N_STARTUP_LINE 2 // Integer (1-2)\n\n// Number of floating decimal points printed by Grbl for certain value types. These settings are \n// determined by realistic and commonly observed values in CNC machines. For example, position\n// values cannot be less than 0.001mm or 0.0001in, because machines can not be physically more\n// precise this. So, there is likely no need to change these, but you can if you need to here.\n// NOTE: Must be an integer value from 0 to ~4. More than 4 may exhibit round-off errors.\n#define N_DECIMAL_COORDVALUE_INCH 4 // Coordinate or position value in inches\n#define N_DECIMAL_COORDVALUE_MM   3 // Coordinate or position value in mm\n#define N_DECIMAL_RATEVALUE_INCH  1 // Rate or velocity value in in/min\n#define N_DECIMAL_RATEVALUE_MM    0 // Rate or velocity value in mm/min\n#define N_DECIMAL_SETTINGVALUE    3 // Decimals for floating point setting values\n\n// If your machine has two limits switches wired in parallel to one axis, you will need to enable\n// this feature. Since the two switches are sharing a single pin, there is no way for Grbl to tell\n// which one is enabled. This option only effects homing, where if a limit is engaged, Grbl will \n// alarm out and force the user to manually disengage the limit switch. Otherwise, if you have one\n// limit switch for each axis, don't enable this option. By keeping it disabled, you can perform a\n// homing cycle while on the limit switch and not have to move the machine off of it.\n// #define LIMITS_TWO_SWITCHES_ON_AXES\n\n// Allows GRBL to track and report gcode line numbers.  Enabling this means that the planning buffer\n// goes from 18 or 16 to make room for the additional line number data in the plan_block_t struct\n// #define USE_LINE_NUMBERS // Disabled by default. Uncomment to enable.\n\n// Allows GRBL to report the real-time feed rate.  Enabling this means that GRBL will be reporting more \n// data with each status update.\n// NOTE: This is experimental and doesn't quite work 100%. Maybe fixed or refactored later.\n// #define REPORT_REALTIME_RATE // Disabled by default. Uncomment to enable.\n\n// Upon a successful probe cycle, this option provides immediately feedback of the probe coordinates\n// through an automatically generated message. If disabled, users can still access the last probe\n// coordinates through Grbl '$#' print parameters.\n#define MESSAGE_PROBE_COORDINATES // Enabled by default. Comment to disable.\n \n// Enables a second coolant control pin via the mist coolant g-code command M7 on the Arduino Uno\n// analog pin 5. Only use this option if you require a second coolant control pin.\n// NOTE: The M8 flood coolant control pin on analog pin 4 will still be functional regardless.\n// #define ENABLE_M7 // Disabled by default. Uncomment to enable.\n\n// This option causes the feed hold input to act as a safety door switch. A safety door, when triggered,\n// immediately forces a feed hold and then safely de-energizes the machine. Resuming is blocked until\n// the safety door is re-engaged. When it is, Grbl will re-energize the machine and then resume on the\n// previous tool path, as if nothing happened.\n// #define ENABLE_SAFETY_DOOR_INPUT_PIN // Default disabled. Uncomment to enable.\n\n// After the safety door switch has been toggled and restored, this setting sets the power-up delay\n// between restoring the spindle and coolant and resuming the cycle.\n// NOTE: Delay value is defined in milliseconds from zero to 65,535. \n#define SAFETY_DOOR_SPINDLE_DELAY 4000\n#define SAFETY_DOOR_COOLANT_DELAY 1000\n\n// Enable CoreXY kinematics. Use ONLY with CoreXY machines. \n// IMPORTANT: If homing is enabled, you must reconfigure the homing cycle #defines above to \n// #define HOMING_CYCLE_0 (1<<X_AXIS) and #define HOMING_CYCLE_1 (1<<Y_AXIS)\n// NOTE: This configuration option alters the motion of the X and Y axes to principle of operation\n// defined at (http://corexy.com/theory.html). Motors are assumed to positioned and wired exactly as\n// described, if not, motions may move in strange directions. Grbl assumes the CoreXY A and B motors\n// have the same steps per mm internally.\n// #define COREXY // Default disabled. Uncomment to enable.\n\n// Inverts pin logic of the control command pins. This essentially means when this option is enabled\n// you can use normally-closed switches, rather than the default normally-open switches.\n// NOTE: Will eventually be added to Grbl settings in v1.0.\n// #define INVERT_CONTROL_PIN // Default disabled. Uncomment to enable.\n\n// Inverts the spindle enable pin from low-disabled/high-enabled to low-enabled/high-disabled. Useful\n// for some pre-built electronic boards.\n// NOTE: If VARIABLE_SPINDLE is enabled(default), this option has no effect as the PWM output and \n// spindle enable are combined to one pin. If you need both this option and spindle speed PWM, \n// uncomment the config option USE_SPINDLE_DIR_AS_ENABLE_PIN below.\n// #define INVERT_SPINDLE_ENABLE_PIN // Default disabled. Uncomment to enable.\n\n// Enable control pin states feedback in status reports. The data is presented as simple binary of\n// the control pin port (0 (low) or 1(high)), masked to show only the input pins. Non-control pins on the \n// port will always show a 0 value. See cpu_map.h for the pin bitmap. As with the limit pin reporting,\n// we do not recommend keeping this option enabled. Try to only use this for setting up a new CNC.\n// #define REPORT_CONTROL_PIN_STATE // Default disabled. Uncomment to enable.\n\n// When Grbl powers-cycles or is hard reset with the Arduino reset button, Grbl boots up with no ALARM\n// by default. This is to make it as simple as possible for new users to start using Grbl. When homing\n// is enabled and a user has installed limit switches, Grbl will boot up in an ALARM state to indicate \n// Grbl doesn't know its position and to force the user to home before proceeding. This option forces\n// Grbl to always initialize into an ALARM state regardless of homing or not. This option is more for\n// OEMs and LinuxCNC users that would like this power-cycle behavior.\n// #define FORCE_INITIALIZATION_ALARM // Default disabled. Uncomment to enable.\n\n// ---------------------------------------------------------------------------------------\n// ADVANCED CONFIGURATION OPTIONS:\n\n// Enables minimal reporting feedback mode for GUIs, where human-readable strings are not as important.\n// This saves nearly 2KB of flash space and may allow enough space to install other/future features.\n// GUIs will need to install a look-up table for the error-codes that Grbl sends back in their place.\n// NOTE: This feature is new and experimental. Make sure the GUI you are using supports this mode.\n// #define REPORT_GUI_MODE // Default disabled. Uncomment to enable.\n\n// The temporal resolution of the acceleration management subsystem. A higher number gives smoother\n// acceleration, particularly noticeable on machines that run at very high feedrates, but may negatively\n// impact performance. The correct value for this parameter is machine dependent, so it's advised to\n// set this only as high as needed. Approximate successful values can widely range from 50 to 200 or more.\n// NOTE: Changing this value also changes the execution time of a segment in the step segment buffer. \n// When increasing this value, this stores less overall time in the segment buffer and vice versa. Make\n// certain the step segment buffer is increased/decreased to account for these changes.\n#define ACCELERATION_TICKS_PER_SECOND 100 \n\n// Adaptive Multi-Axis Step Smoothing (AMASS) is an advanced feature that does what its name implies, \n// smoothing the stepping of multi-axis motions. This feature smooths motion particularly at low step\n// frequencies below 10kHz, where the aliasing between axes of multi-axis motions can cause audible \n// noise and shake your machine. At even lower step frequencies, AMASS adapts and provides even better\n// step smoothing. See stepper.c for more details on the AMASS system works.\n#define ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING  // Default enabled. Comment to disable.\n\n// Sets the maximum step rate allowed to be written as a Grbl setting. This option enables an error \n// check in the settings module to prevent settings values that will exceed this limitation. The maximum\n// step rate is strictly limited by the CPU speed and will change if something other than an AVR running\n// at 16MHz is used.\n// NOTE: For now disabled, will enable if flash space permits.\n// #define MAX_STEP_RATE_HZ 30000 // Hz\n\n// By default, Grbl sets all input pins to normal-high operation with their internal pull-up resistors\n// enabled. This simplifies the wiring for users by requiring only a switch connected to ground, \n// although its recommended that users take the extra step of wiring in low-pass filter to reduce\n// electrical noise detected by the pin. If the user inverts the pin in Grbl settings, this just flips\n// which high or low reading indicates an active signal. In normal operation, this means the user \n// needs to connect a normal-open switch, but if inverted, this means the user should connect a \n// normal-closed switch. \n// The following options disable the internal pull-up resistors, sets the pins to a normal-low \n// operation, and switches must be now connect to Vcc instead of ground. This also flips the meaning \n// of the invert pin Grbl setting, where an inverted setting now means the user should connect a \n// normal-open switch and vice versa.\n// NOTE: All pins associated with the feature are disabled, i.e. XYZ limit pins, not individual axes.\n// WARNING: When the pull-ups are disabled, this requires additional wiring with pull-down resistors!\n//#define DISABLE_LIMIT_PIN_PULL_UP\n//#define DISABLE_PROBE_PIN_PULL_UP\n//#define DISABLE_CONTROL_PIN_PULL_UP\n\n// Sets which axis the tool length offset is applied. Assumes the spindle is always parallel with \n// the selected axis with the tool oriented toward the negative direction. In other words, a positive\n// tool length offset value is subtracted from the current location.\n#define TOOL_LENGTH_OFFSET_AXIS Z_AXIS // Default z-axis. Valid values are X_AXIS, Y_AXIS, or Z_AXIS.\n\n// Enables variable spindle output voltage for different RPM values. On the Arduino Uno, the spindle\n// enable pin will output 5V for maximum RPM with 256 intermediate levels and 0V when disabled.\n// NOTE: IMPORTANT for Arduino Unos! When enabled, the Z-limit pin D11 and spindle enable pin D12 switch!\n// The hardware PWM output on pin D11 is required for variable spindle output voltages.\n#define VARIABLE_SPINDLE // Default enabled. Comment to disable.\n\n// Used by the variable spindle output only. These parameters set the maximum and minimum spindle speed\n// \"S\" g-code values to correspond to the maximum and minimum pin voltages. There are 256 discrete and \n// equally divided voltage bins between the maximum and minimum spindle speeds. So for a 5V pin, 1000\n// max rpm, and 250 min rpm, the spindle output voltage would be set for the following \"S\" commands: \n// \"S1000\" @ 5V, \"S250\" @ 0.02V, and \"S625\" @ 2.5V (mid-range). The pin outputs 0V when disabled.\n#define SPINDLE_MAX_RPM 90 // Max spindle RPM. This value is equal to 100% duty cycle on the PWM.\n#define SPINDLE_MIN_RPM 0.0    // Min spindle RPM. This value is equal to (1/256) duty cycle on the PWM.\n\n// Used by variable spindle output only. This forces the PWM output to a minimum duty cycle when enabled.\n// When disabled, the PWM pin will still read 0V. Most users will not need this option, but it may be \n// useful in certain scenarios. This setting does not update the minimum spindle RPM calculations. Any\n// spindle RPM output lower than this value will be set to this value.\n// #define MINIMUM_SPINDLE_PWM 5 // Default disabled. Uncomment to enable. Integer (0-255)\n\n// By default on a 328p(Uno), Grbl combines the variable spindle PWM and the enable into one pin to help \n// preserve I/O pins. For certain setups, these may need to be separate pins. This configure option uses\n// the spindle direction pin(D13) as a separate spindle enable pin along with spindle speed PWM on pin D11. \n// NOTE: This configure option only works with VARIABLE_SPINDLE enabled and a 328p processor (Uno). \n// NOTE: With no direction pin, the spindle clockwise M4 g-code command will be removed. M3 and M5 still work.\n//#define USE_SPINDLE_DIR_AS_ENABLE_PIN // Default disabled. Uncomment to enable.\n\n// With this enabled, Grbl sends back an echo of the line it has received, which has been pre-parsed (spaces\n// removed, capitalized letters, no comments) and is to be immediately executed by Grbl. Echoes will not be \n// sent upon a line buffer overflow, but should for all normal lines sent to Grbl. For example, if a user \n// sendss the line 'g1 x1.032 y2.45 (test comment)', Grbl will echo back in the form '[echo: G1X1.032Y2.45]'.\n// NOTE: Only use this for debugging purposes!! When echoing, this takes up valuable resources and can effect\n// performance. If absolutely needed for normal operation, the serial write buffer should be greatly increased\n// to help minimize transmission waiting within the serial write protocol.\n// #define REPORT_ECHO_LINE_RECEIVED // Default disabled. Uncomment to enable.\n\n// Minimum planner junction speed. Sets the default minimum junction speed the planner plans to at\n// every buffer block junction, except for starting from rest and end of the buffer, which are always\n// zero. This value controls how fast the machine moves through junctions with no regard for acceleration\n// limits or angle between neighboring block line move directions. This is useful for machines that can't\n// tolerate the tool dwelling for a split second, i.e. 3d printers or laser cutters. If used, this value\n// should not be much greater than zero or to the minimum value necessary for the machine to work.\n#define MINIMUM_JUNCTION_SPEED 0.0 // (mm/min)\n\n// Sets the minimum feed rate the planner will allow. Any value below it will be set to this minimum\n// value. This also ensures that a planned motion always completes and accounts for any floating-point\n// round-off errors. Although not recommended, a lower value than 1.0 mm/min will likely work in smaller\n// machines, perhaps to 0.1mm/min, but your success may vary based on multiple factors.\n#define MINIMUM_FEED_RATE 1.0 // (mm/min)\n\n// Number of arc generation iterations by small angle approximation before exact arc trajectory \n// correction with expensive sin() and cos() calcualtions. This parameter maybe decreased if there \n// are issues with the accuracy of the arc generations, or increased if arc execution is getting\n// bogged down by too many trig calculations. \n#define N_ARC_CORRECTION 12 // Integer (1-255)\n\n// The arc G2/3 g-code standard is problematic by definition. Radius-based arcs have horrible numerical \n// errors when arc at semi-circles(pi) or full-circles(2*pi). Offset-based arcs are much more accurate \n// but still have a problem when arcs are full-circles (2*pi). This define accounts for the floating \n// point issues when offset-based arcs are commanded as full circles, but get interpreted as extremely\n// small arcs with around machine epsilon (1.2e-7rad) due to numerical round-off and precision issues.\n// This define value sets the machine epsilon cutoff to determine if the arc is a full-circle or not.\n// NOTE: Be very careful when adjusting this value. It should always be greater than 1.2e-7 but not too\n// much greater than this. The default setting should capture most, if not all, full arc error situations.\n#define ARC_ANGULAR_TRAVEL_EPSILON 5E-7 // Float (radians)\n\n// Time delay increments performed during a dwell. The default value is set at 50ms, which provides\n// a maximum time delay of roughly 55 minutes, more than enough for most any application. Increasing\n// this delay will increase the maximum dwell time linearly, but also reduces the responsiveness of \n// run-time command executions, like status reports, since these are performed between each dwell \n// time step. Also, keep in mind that the Arduino delay timer is not very accurate for long delays.\n#define DWELL_TIME_STEP 50 // Integer (1-255) (milliseconds)\n\n// Creates a delay between the direction pin setting and corresponding step pulse by creating\n// another interrupt (Timer2 compare) to manage it. The main Grbl interrupt (Timer1 compare) \n// sets the direction pins, and does not immediately set the stepper pins, as it would in \n// normal operation. The Timer2 compare fires next to set the stepper pins after the step \n// pulse delay time, and Timer2 overflow will complete the step pulse, except now delayed \n// by the step pulse time plus the step pulse delay. (Thanks langwadt for the idea!)\n// NOTE: Uncomment to enable. The recommended delay must be > 3us, and, when added with the\n// user-supplied step pulse time, the total time must not exceed 127us. Reported successful\n// values for certain setups have ranged from 5 to 20us.\n// #define STEP_PULSE_DELAY 10 // Step pulse delay in microseconds. Default disabled.\n\n// The number of linear motions in the planner buffer to be planned at any give time. The vast\n// majority of RAM that Grbl uses is based on this buffer size. Only increase if there is extra \n// available RAM, like when re-compiling for a Mega or Sanguino. Or decrease if the Arduino\n// begins to crash due to the lack of available RAM or if the CPU is having trouble keeping\n// up with planning new incoming motions as they are executed. \n// #define BLOCK_BUFFER_SIZE 18  // Uncomment to override default in planner.h.\n\n// Governs the size of the intermediary step segment buffer between the step execution algorithm\n// and the planner blocks. Each segment is set of steps executed at a constant velocity over a\n// fixed time defined by ACCELERATION_TICKS_PER_SECOND. They are computed such that the planner\n// block velocity profile is traced exactly. The size of this buffer governs how much step \n// execution lead time there is for other Grbl processes have to compute and do their thing \n// before having to come back and refill this buffer, currently at ~50msec of step moves.\n// #define SEGMENT_BUFFER_SIZE 6 // Uncomment to override default in stepper.h.\n\n// Line buffer size from the serial input stream to be executed. Also, governs the size of \n// each of the startup blocks, as they are each stored as a string of this size. Make sure\n// to account for the available EEPROM at the defined memory address in settings.h and for\n// the number of desired startup blocks.\n// NOTE: 80 characters is not a problem except for extreme cases, but the line buffer size \n// can be too small and g-code blocks can get truncated. Officially, the g-code standards \n// support up to 256 characters. In future versions, this default will be increased, when \n// we know how much extra memory space we can re-invest into this.\n// #define LINE_BUFFER_SIZE 80  // Uncomment to override default in protocol.h\n  \n// Serial send and receive buffer size. The receive buffer is often used as another streaming\n// buffer to store incoming blocks to be processed by Grbl when its ready. Most streaming\n// interfaces will character count and track each block send to each block response. So, \n// increase the receive buffer if a deeper receive buffer is needed for streaming and avaiable\n// memory allows. The send buffer primarily handles messages in Grbl. Only increase if large\n// messages are sent and Grbl begins to stall, waiting to send the rest of the message.\n// NOTE: Buffer size values must be greater than zero and less than 256.\n// #define RX_BUFFER_SIZE 128 // Uncomment to override defaults in serial.h\n// #define TX_BUFFER_SIZE 64\n  \n// Toggles XON/XOFF software flow control for serial communications. Not officially supported\n// due to problems involving the Atmega8U2 USB-to-serial chips on current Arduinos. The firmware\n// on these chips do not support XON/XOFF flow control characters and the intermediate buffer \n// in the chips cause latency and overflow problems with standard terminal programs. However, \n// using specifically-programmed UI's to manage this latency problem has been confirmed to work.\n// As well as, older FTDI FT232RL-based Arduinos(Duemilanove) are known to work with standard\n// terminal programs since their firmware correctly manage these XON/XOFF characters. In any\n// case, please report any successes to grbl administrators!\n// #define ENABLE_XONXOFF // Default disabled. Uncomment to enable.\n\n// A simple software debouncing feature for hard limit switches. When enabled, the interrupt \n// monitoring the hard limit switch pins will enable the Arduino's watchdog timer to re-check \n// the limit pin state after a delay of about 32msec. This can help with CNC machines with \n// problematic false triggering of their hard limit switches, but it WILL NOT fix issues with \n// electrical interference on the signal cables from external sources. It's recommended to first\n// use shielded signal cables with their shielding connected to ground (old USB/computer cables \n// work well and are cheap to find) and wire in a low-pass circuit into each limit pin.\n// #define ENABLE_SOFTWARE_DEBOUNCE // Default disabled. Uncomment to enable.\n\n// Force Grbl to check the state of the hard limit switches when the processor detects a pin\n// change inside the hard limit ISR routine. By default, Grbl will trigger the hard limits\n// alarm upon any pin change, since bouncing switches can cause a state check like this to \n// misread the pin. When hard limits are triggered, they should be 100% reliable, which is the\n// reason that this option is disabled by default. Only if your system/electronics can guarantee\n// that the switches don't bounce, we recommend enabling this option. This will help prevent\n// triggering a hard limit when the machine disengages from the switch.\n// NOTE: This option has no effect if SOFTWARE_DEBOUNCE is enabled.\n// #define HARD_LIMIT_FORCE_STATE_CHECK // Default disabled. Uncomment to enable.\n\n\n// ---------------------------------------------------------------------------------------\n// COMPILE-TIME ERROR CHECKING OF DEFINE VALUES:\n\n#ifndef HOMING_CYCLE_0\n  #error \"Required HOMING_CYCLE_0 not defined.\"\n#endif\n\n#if defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && !defined(VARIABLE_SPINDLE)\n  #error \"USE_SPINDLE_DIR_AS_ENABLE_PIN may only be used with VARIABLE_SPINDLE enabled\"\n#endif\n\n#if defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && !defined(CPU_MAP_ATMEGA328P)\n  #error \"USE_SPINDLE_DIR_AS_ENABLE_PIN may only be used with a 328p processor\"\n#endif\n\n// ---------------------------------------------------------------------------------------\n\n\n#endif\n"
  },
  {
    "path": "coolant_control.c",
    "content": "/*\n  coolant_control.c - coolant control methods\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/  \n\n#include \"grbl.h\"\n\n\nvoid coolant_init()\n{\n  COOLANT_FLOOD_DDR |= (1 << COOLANT_FLOOD_BIT);\n  #ifdef ENABLE_M7\n    COOLANT_MIST_DDR |= (1 << COOLANT_MIST_BIT);\n  #endif\n  coolant_stop();\n}\n\n\nvoid coolant_stop()\n{\n  COOLANT_FLOOD_PORT &= ~(1 << COOLANT_FLOOD_BIT);\n  #ifdef ENABLE_M7\n    COOLANT_MIST_PORT &= ~(1 << COOLANT_MIST_BIT);\n  #endif\n}\n\n\nvoid coolant_set_state(uint8_t mode)\n{\n  if (mode == COOLANT_FLOOD_ENABLE) {\n    COOLANT_FLOOD_PORT |= (1 << COOLANT_FLOOD_BIT);\n\n  #ifdef ENABLE_M7  \n    } else if (mode == COOLANT_MIST_ENABLE) {\n      COOLANT_MIST_PORT |= (1 << COOLANT_MIST_BIT);\n  #endif\n\n  } else {\n    coolant_stop();\n  }\n}\n\n\nvoid coolant_run(uint8_t mode)\n{\n  if (sys.state == STATE_CHECK_MODE) { return; }\n  protocol_buffer_synchronize(); // Ensure coolant turns on when specified in program.  \n  coolant_set_state(mode);\n}\n"
  },
  {
    "path": "coolant_control.h",
    "content": "/*\n  coolant_control.h - spindle control methods\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef coolant_control_h\n#define coolant_control_h \n\n\nvoid coolant_init();\nvoid coolant_stop();\nvoid coolant_set_state(uint8_t mode);\nvoid coolant_run(uint8_t mode);\n\n#endif"
  },
  {
    "path": "cpu_map/cpu_map_atmega2560.h",
    "content": "/*\n  cpu_map_atmega2560.h - CPU and pin mapping configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* This cpu_map file serves as a central pin mapping settings file for AVR Mega 2560 */\n\n\n#ifdef GRBL_PLATFORM\n#error \"cpu_map already defined: GRBL_PLATFORM=\" GRBL_PLATFORM\n#endif\n\n\n#define GRBL_PLATFORM \"Atmega2560\"\n\n// Serial port pins\n#define SERIAL_RX USART0_RX_vect\n#define SERIAL_UDRE USART0_UDRE_vect\n\n// Increase Buffers to make use of extra SRAM\n//#define RX_BUFFER_SIZE\t\t256\n//#define TX_BUFFER_SIZE\t\t128\n//#define BLOCK_BUFFER_SIZE\t36\n//#define LINE_BUFFER_SIZE\t100\n\n// Define step pulse output pins. NOTE: All step bit pins must be on the same port.\n#define STEP_DDR      DDRA\n#define STEP_PORT     PORTA\n#define STEP_PIN      PINA\n#define X_STEP_BIT    2 // MEGA2560 Digital Pin 24\n#define Y_STEP_BIT    3 // MEGA2560 Digital Pin 25\n#define Z_STEP_BIT    4 // MEGA2560 Digital Pin 26\n#define STEP_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT)) // All step bits\n\n// Define step direction output pins. NOTE: All direction pins must be on the same port.\n#define DIRECTION_DDR     DDRC\n#define DIRECTION_PORT    PORTC\n#define DIRECTION_PIN     PINC\n#define X_DIRECTION_BIT   7 // MEGA2560 Digital Pin 30\n#define Y_DIRECTION_BIT   6 // MEGA2560 Digital Pin 31\n#define Z_DIRECTION_BIT   5 // MEGA2560 Digital Pin 32\n#define DIRECTION_MASK ((1<<X_DIRECTION_BIT)|(1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)) // All direction bits\n\n// Define stepper driver enable/disable output pin.\n#define STEPPERS_DISABLE_DDR   DDRB\n#define STEPPERS_DISABLE_PORT  PORTB\n#define STEPPERS_DISABLE_BIT   7 // MEGA2560 Digital Pin 13\n#define STEPPERS_DISABLE_MASK (1<<STEPPERS_DISABLE_BIT)\n\n// Define homing/hard limit switch input pins and limit interrupt vectors. \n// NOTE: All limit bit pins must be on the same port\n#define LIMIT_DDR       DDRB\n#define LIMIT_PORT      PORTB\n#define LIMIT_PIN       PINB\n#define X_LIMIT_BIT     4 // MEGA2560 Digital Pin 10\n#define Y_LIMIT_BIT     5 // MEGA2560 Digital Pin 11\n#define Z_LIMIT_BIT     6 // MEGA2560 Digital Pin 12\n#define LIMIT_INT       PCIE0  // Pin change interrupt enable pin\n#define LIMIT_INT_vect  PCINT0_vect \n#define LIMIT_PCMSK     PCMSK0 // Pin change interrupt register\n#define LIMIT_MASK ((1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)|(1<<Z_LIMIT_BIT)) // All limit bits\n\n// Define spindle enable and spindle direction output pins.\n#define SPINDLE_ENABLE_DDR      DDRH\n#define SPINDLE_ENABLE_PORT     PORTH\n#define SPINDLE_ENABLE_BIT      3 // MEGA2560 Digital Pin 6\n#define SPINDLE_DIRECTION_DDR   DDRE\n#define SPINDLE_DIRECTION_PORT  PORTE\n#define SPINDLE_DIRECTION_BIT   3 // MEGA2560 Digital Pin 5\n\n// Define flood and mist coolant enable output pins.\n// NOTE: Uno analog pins 4 and 5 are reserved for an i2c interface, and may be installed at\n// a later date if flash and memory space allows.\n#define COOLANT_FLOOD_DDR     DDRH\n#define COOLANT_FLOOD_PORT    PORTH\n#define COOLANT_FLOOD_BIT     5 // MEGA2560 Digital Pin 8\n#ifdef ENABLE_M7 // Mist coolant disabled by default. See config.h to enable/disable.\n#define COOLANT_MIST_DDR    DDRH\n#define COOLANT_MIST_PORT   PORTH\n#define COOLANT_MIST_BIT    6 // MEGA2560 Digital Pin 9\n#endif  \n\n// Define user-control CONTROLs (cycle start, reset, feed hold) input pins.\n// NOTE: All CONTROLs pins must be on the same port and not on a port with other input pins (limits).\n#define CONTROL_DDR       DDRK\n#define CONTROL_PIN       PINK\n#define CONTROL_PORT      PORTK\n#define RESET_BIT         0  // MEGA2560 Analog Pin 8\n#define FEED_HOLD_BIT     1  // MEGA2560 Analog Pin 9\n#define CYCLE_START_BIT   2  // MEGA2560 Analog Pin 10\n#define SAFETY_DOOR_BIT   3  // MEGA2560 Analog Pin 11\n#define CONTROL_INT       PCIE2  // Pin change interrupt enable pin\n#define CONTROL_INT_vect  PCINT2_vect\n#define CONTROL_PCMSK     PCMSK2 // Pin change interrupt register\n#define CONTROL_MASK ((1<<RESET_BIT)|(1<<FEED_HOLD_BIT)|(1<<CYCLE_START_BIT)|(1<<SAFETY_DOOR_BIT))\n\n// Define probe switch input pin.\n#define PROBE_DDR       DDRK\n#define PROBE_PIN       PINK\n#define PROBE_PORT      PORTK\n#define PROBE_BIT       7  // MEGA2560 Analog Pin 15\n#define PROBE_MASK      (1<<PROBE_BIT)\n\n// Start of PWM & Stepper Enabled Spindle\n#ifdef VARIABLE_SPINDLE\n  // Advanced Configuration Below You should not need to touch these variables\n  // Set Timer up to use TIMER4B which is attached to Digital Pin 7\n  #define PWM_MAX_VALUE       65535.0\n  #define TCCRA_REGISTER\t\tTCCR4A\n  #define TCCRB_REGISTER\t\tTCCR4B\n  #define OCR_REGISTER\t\tOCR4B\n  \n  #define COMB_BIT\t\t\tCOM4B1\n  #define WAVE0_REGISTER\t\tWGM40\n  #define WAVE1_REGISTER\t\tWGM41\n  #define WAVE2_REGISTER\t\tWGM42\n  #define WAVE3_REGISTER\t\tWGM43\n  \n  #define SPINDLE_PWM_DDR\t\tDDRH\n  #define SPINDLE_PWM_PORT    PORTH\n  #define SPINDLE_PWM_BIT\t\t4 // MEGA2560 Digital Pin 97\n#endif // End of VARIABLE_SPINDLE\n"
  },
  {
    "path": "cpu_map/cpu_map_atmega328p.h",
    "content": "/*\n  cpu_map_atmega328p.h - CPU and pin mapping configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* Grbl officially supports the Arduino Uno, but the other supplied pin mappings are\n   supplied by users, so your results may vary. This cpu_map file serves as a central\n   pin mapping settings file for AVR 328p used on the Arduino Uno.  */\n   \n#ifdef GRBL_PLATFORM\n#error \"cpu_map already defined: GRBL_PLATFORM=\" GRBL_PLATFORM\n#endif\n\n\n#define GRBL_PLATFORM \"Atmega328p\"\n\n// Define serial port pins and interrupt vectors.\n#define SERIAL_RX     USART_RX_vect\n#define SERIAL_UDRE   USART_UDRE_vect\n\n// Define step pulse output pins. NOTE: All step bit pins must be on the same port.\n#define STEP_DDR        DDRD\n#define STEP_PORT       PORTD\n#define X_STEP_BIT      2  // Uno Digital Pin 2\n#define Y_STEP_BIT      3  // Uno Digital Pin 3\n#define Z_STEP_BIT      4  // Uno Digital Pin 4\n#define STEP_MASK       ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT)) // All step bits\n\n// Define step direction output pins. NOTE: All direction pins must be on the same port.\n#define DIRECTION_DDR     DDRD\n#define DIRECTION_PORT    PORTD\n#define X_DIRECTION_BIT   5  // Uno Digital Pin 5\n#define Y_DIRECTION_BIT   6  // Uno Digital Pin 6\n#define Z_DIRECTION_BIT   7  // Uno Digital Pin 7\n#define DIRECTION_MASK    ((1<<X_DIRECTION_BIT)|(1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)) // All direction bits\n\n// Define stepper driver enable/disable output pin.\n#define STEPPERS_DISABLE_DDR    DDRB\n#define STEPPERS_DISABLE_PORT   PORTB\n#define STEPPERS_DISABLE_BIT    0  // Uno Digital Pin 8\n#define STEPPERS_DISABLE_MASK   (1<<STEPPERS_DISABLE_BIT)\n\n// Define homing/hard limit switch input pins and limit interrupt vectors. \n// NOTE: All limit bit pins must be on the same port, but not on a port with other input pins (CONTROL).\n#define LIMIT_DDR        DDRB\n#define LIMIT_PIN        PINB\n#define LIMIT_PORT       PORTB\n#define X_LIMIT_BIT      1  // Uno Digital Pin 9\n#define Y_LIMIT_BIT      2  // Uno Digital Pin 10\n#ifdef VARIABLE_SPINDLE // Z Limit pin and spindle enabled swapped to access hardware PWM on Pin 11.  \n  #define Z_LIMIT_BIT\t   4 // Uno Digital Pin 12\n#else\n  #define Z_LIMIT_BIT    3  // Uno Digital Pin 11\n#endif\n#define LIMIT_MASK       ((1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)|(1<<Z_LIMIT_BIT)) // All limit bits\n#define LIMIT_INT        PCIE0  // Pin change interrupt enable pin\n#define LIMIT_INT_vect   PCINT0_vect \n#define LIMIT_PCMSK      PCMSK0 // Pin change interrupt register\n\n// Define spindle enable and spindle direction output pins.\n#define SPINDLE_ENABLE_DDR    DDRB\n#define SPINDLE_ENABLE_PORT   PORTB\n// Z Limit pin and spindle PWM/enable pin swapped to access hardware PWM on Pin 11.\n#ifdef VARIABLE_SPINDLE \n  #ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN\n    // If enabled, spindle direction pin now used as spindle enable, while PWM remains on D11.\n    #define SPINDLE_ENABLE_BIT    5  // Uno Digital Pin 13 (NOTE: D13 can't be pulled-high input due to LED.)\n  #else\n    #define SPINDLE_ENABLE_BIT    3  // Uno Digital Pin 11\n  #endif\n#else\n  #define SPINDLE_ENABLE_BIT    4  // Uno Digital Pin 12\n#endif\n#ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN\n  #define SPINDLE_DIRECTION_DDR   DDRB\n  #define SPINDLE_DIRECTION_PORT  PORTB\n  #define SPINDLE_DIRECTION_BIT   5  // Uno Digital Pin 13 (NOTE: D13 can't be pulled-high input due to LED.)\n#endif\n  \n// Define flood and mist coolant enable output pins.\n// NOTE: Uno analog pins 4 and 5 are reserved for an i2c interface, and may be installed at\n// a later date if flash and memory space allows.\n#define COOLANT_FLOOD_DDR   DDRC\n#define COOLANT_FLOOD_PORT  PORTC\n#define COOLANT_FLOOD_BIT   3  // Uno Analog Pin 3\n#ifdef ENABLE_M7 // Mist coolant disabled by default. See config.h to enable/disable.\n  #define COOLANT_MIST_DDR   DDRC\n  #define COOLANT_MIST_PORT  PORTC\n  #define COOLANT_MIST_BIT   4 // Uno Analog Pin 4\n#endif  \n\n// Define user-control controls (cycle start, reset, feed hold) input pins.\n// NOTE: All CONTROLs pins must be on the same port and not on a port with other input pins (limits).\n#define CONTROL_DDR       DDRC\n#define CONTROL_PIN       PINC\n#define CONTROL_PORT      PORTC\n#define RESET_BIT         0  // Uno Analog Pin 0\n#define FEED_HOLD_BIT     1  // Uno Analog Pin 1\n#define CYCLE_START_BIT   2  // Uno Analog Pin 2\n#define SAFETY_DOOR_BIT   1  // Uno Analog Pin 1 NOTE: Safety door is shared with feed hold. Enabled by config define.\n#define CONTROL_INT       PCIE1  // Pin change interrupt enable pin\n#define CONTROL_INT_vect  PCINT1_vect\n#define CONTROL_PCMSK     PCMSK1 // Pin change interrupt register\n#define CONTROL_MASK ((1<<RESET_BIT)|(1<<FEED_HOLD_BIT)|(1<<CYCLE_START_BIT)|(1<<SAFETY_DOOR_BIT))\n  \n// Define probe switch input pin.\n#define PROBE_DDR       DDRC\n#define PROBE_PIN       PINC\n#define PROBE_PORT      PORTC\n#define PROBE_BIT       5  // Uno Analog Pin 5\n#define PROBE_MASK      (1<<PROBE_BIT)\n\n// Start of PWM & Stepper Enabled Spindle\n#ifdef VARIABLE_SPINDLE\n  // Advanced Configuration Below You should not need to touch these variables\n  #define PWM_MAX_VALUE    255.0\n  #define TCCRA_REGISTER\t TCCR2A\n  #define TCCRB_REGISTER\t TCCR2B\n  #define OCR_REGISTER     OCR2A\n  \n  #define COMB_BIT\t     COM2A1\n  #define WAVE0_REGISTER\t WGM20\n  #define WAVE1_REGISTER\t WGM21\n  #define WAVE2_REGISTER\t WGM22\n  #define WAVE3_REGISTER\t WGM23\n      \n  // NOTE: On the 328p, these must be the same as the SPINDLE_ENABLE settings.\n  #define SPINDLE_PWM_DDR\t  DDRB\n  #define SPINDLE_PWM_PORT  PORTB\n  #define SPINDLE_PWM_BIT\t  3    // Uno Digital Pin 11\n#endif // End of VARIABLE_SPINDLE\n"
  },
  {
    "path": "cpu_map.h",
    "content": "/*\n  cpu_map.h - CPU and pin mapping configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The cpu_map.h files serve as a central pin mapping selection file for different processor\n   types, i.e. AVR 328p or AVR Mega 2560. Each processor has its own pin mapping file.\n   (i.e. cpu_map_atmega328p.h)  Grbl officially supports the Arduino Uno, but the \n   other supplied pin mappings are supplied by users, so your results may vary. */\n\n// NOTE: With new processors, only add the define name and filename to use.\n\n#ifndef cpu_map_h\n#define cpu_map_h\n\n\n#ifdef CPU_MAP_ATMEGA328P // (Arduino Uno) Officially supported by Grbl.\n  #include \"cpu_map/cpu_map_atmega328p.h\"\n#endif\n\n#ifdef CPU_MAP_ATMEGA2560 // (Arduino Mega 2560) Working @EliteEng\n  #include \"cpu_map/cpu_map_atmega2560.h\"\n#endif\n\n/* \n#ifdef CPU_MAP_CUSTOM_PROC\n  // For a custom pin map or different processor, copy and edit one of the available cpu\n  // map files and modify it to your needs. Make sure the defined name is also changed in\n  // the config.h file.\n#endif\n*/\n\n#endif\n"
  },
  {
    "path": "defaults/defaults_generic.h",
    "content": "/*\n  defaults_generic.h - defaults settings configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The defaults.h file serves as a central default settings file for different machine\n   types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings\n   here are supplied by users, so your results may vary. However, this should give you\n   a good starting point as you get to know your machine and tweak the settings for your\n   nefarious needs. */\n\n#ifndef defaults_h\n#define defaults_h\n\n  // Grbl generic default settings. Should work across different machines.\n  #define DEFAULT_X_STEPS_PER_MM 250.0\n  #define DEFAULT_Y_STEPS_PER_MM 250.0\n  #define DEFAULT_Z_STEPS_PER_MM 250.0\n  #define DEFAULT_X_MAX_RATE 500.0 // mm/min\n  #define DEFAULT_Y_MAX_RATE 500.0 // mm/min\n  #define DEFAULT_Z_MAX_RATE 500.0 // mm/min\n  #define DEFAULT_X_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2\n  #define DEFAULT_Y_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2\n  #define DEFAULT_Z_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2\n  #define DEFAULT_X_MAX_TRAVEL 200.0 // mm\n  #define DEFAULT_Y_MAX_TRAVEL 200.0 // mm\n  #define DEFAULT_Z_MAX_TRAVEL 200.0 // mm\n  #define DEFAULT_STEP_PULSE_MICROSECONDS 10\n  #define DEFAULT_STEPPING_INVERT_MASK 0\n  #define DEFAULT_DIRECTION_INVERT_MASK 0\n  #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)\n  #define DEFAULT_STATUS_REPORT_MASK ((BITFLAG_RT_STATUS_MACHINE_POSITION)|(BITFLAG_RT_STATUS_WORK_POSITION))\n  #define DEFAULT_JUNCTION_DEVIATION 0.01 // mm\n  #define DEFAULT_ARC_TOLERANCE 0.002 // mm\n  #define DEFAULT_REPORT_INCHES 0 // false\n  #define DEFAULT_INVERT_ST_ENABLE 0 // false\n  #define DEFAULT_INVERT_LIMIT_PINS 0 // false\n  #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false\n  #define DEFAULT_HARD_LIMIT_ENABLE 0  // false\n  #define DEFAULT_HOMING_ENABLE 0  // false\n  #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir\n  #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min\n  #define DEFAULT_HOMING_SEEK_RATE 500.0 // mm/min\n  #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)\n  #define DEFAULT_HOMING_PULLOFF 1.0 // mm\n\n#endif\n"
  },
  {
    "path": "defaults/defaults_oxcnc.h",
    "content": "/*\n  defaults_oxcnc.h - defaults settings configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The defaults.h file serves as a central default settings file for different machine\n   types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings\n   here are supplied by users, so your results may vary. However, this should give you\n   a good starting point as you get to know your machine and tweak the settings for your\n   nefarious needs. */\n\n#ifndef defaults_h\n#define defaults_h\n\n  // Grbl settings for OpenBuilds OX CNC Machine\n  // http://www.openbuilds.com/builds/openbuilds-ox-cnc-machine.341/\n  #define DEFAULT_X_STEPS_PER_MM 26.670\n  #define DEFAULT_Y_STEPS_PER_MM 26.670\n  #define DEFAULT_Z_STEPS_PER_MM 50\n  #define DEFAULT_X_MAX_RATE 500.0 // mm/min\n  #define DEFAULT_Y_MAX_RATE 500.0 // mm/min\n  #define DEFAULT_Z_MAX_RATE 500.0 // mm/min\n  #define DEFAULT_X_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2\n  #define DEFAULT_Y_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2\n  #define DEFAULT_Z_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2\n  #define DEFAULT_X_MAX_TRAVEL 500.0 // mm\n  #define DEFAULT_Y_MAX_TRAVEL 750.0 // mm\n  #define DEFAULT_Z_MAX_TRAVEL 80.0 // mm\n  #define DEFAULT_STEP_PULSE_MICROSECONDS 10\n  #define DEFAULT_STEPPING_INVERT_MASK 0\n  #define DEFAULT_DIRECTION_INVERT_MASK 0\n  #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)\n  #define DEFAULT_STATUS_REPORT_MASK ((BITFLAG_RT_STATUS_MACHINE_POSITION)|(BITFLAG_RT_STATUS_WORK_POSITION))\n  #define DEFAULT_JUNCTION_DEVIATION 0.02 // mm\n  #define DEFAULT_ARC_TOLERANCE 0.002 // mm\n  #define DEFAULT_REPORT_INCHES 0 // false\n  #define DEFAULT_INVERT_ST_ENABLE 0 // false\n  #define DEFAULT_INVERT_LIMIT_PINS 0 // false\n  #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false\n  #define DEFAULT_HARD_LIMIT_ENABLE 0  // false\n  #define DEFAULT_HOMING_ENABLE 0  // false\n  #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir\n  #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min\n  #define DEFAULT_HOMING_SEEK_RATE 500.0 // mm/min\n  #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)\n  #define DEFAULT_HOMING_PULLOFF 1.0 // mm\n\n#endif\n"
  },
  {
    "path": "defaults/defaults_shapeoko.h",
    "content": "/*\n  defaults_shapeoko.h - defaults settings configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The defaults.h file serves as a central default settings file for different machine\n   types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings\n   here are supplied by users, so your results may vary. However, this should give you\n   a good starting point as you get to know your machine and tweak the settings for your\n   nefarious needs. */\n\n#ifndef defaults_h\n#define defaults_h\n\n\n  // Description: Shapeoko CNC mill with three NEMA 17 stepper motors, driven by Synthetos\n  // grblShield with a 24V, 4.2A power supply.\n  #define MICROSTEPS_XY 8\n  #define STEP_REVS_XY 400\n  #define MM_PER_REV_XY (0.08*18*MM_PER_INCH) // 0.08 in belt pitch, 18 pulley teeth\n  #define MICROSTEPS_Z 2\n  #define STEP_REVS_Z 400\n  #define MM_PER_REV_Z 1.250 // 1.25 mm/rev leadscrew\n  #define DEFAULT_X_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)\n  #define DEFAULT_Y_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)\n  #define DEFAULT_Z_STEPS_PER_MM (MICROSTEPS_Z*STEP_REVS_Z/MM_PER_REV_Z)\n  #define DEFAULT_X_MAX_RATE 1000.0 // mm/min\n  #define DEFAULT_Y_MAX_RATE 1000.0 // mm/min\n  #define DEFAULT_Z_MAX_RATE 1000.0 // mm/min\n  #define DEFAULT_X_ACCELERATION (15.0*60*60) // 15*60*60 mm/min^2 = 15 mm/sec^2\n  #define DEFAULT_Y_ACCELERATION (15.0*60*60) // 15*60*60 mm/min^2 = 15 mm/sec^2\n  #define DEFAULT_Z_ACCELERATION (15.0*60*60) // 15*60*60 mm/min^2 = 15 mm/sec^2\n  #define DEFAULT_X_MAX_TRAVEL 200.0 // mm\n  #define DEFAULT_Y_MAX_TRAVEL 200.0 // mm\n  #define DEFAULT_Z_MAX_TRAVEL 200.0 // mm\n  #define DEFAULT_STEP_PULSE_MICROSECONDS 10\n  #define DEFAULT_STEPPING_INVERT_MASK 0\n  #define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_AXIS)|(1<<Z_AXIS))  \n  #define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)\n  #define DEFAULT_STATUS_REPORT_MASK ((BITFLAG_RT_STATUS_MACHINE_POSITION)|(BITFLAG_RT_STATUS_WORK_POSITION))\n  #define DEFAULT_JUNCTION_DEVIATION 0.02 // mm\n  #define DEFAULT_ARC_TOLERANCE 0.002 // mm\n  #define DEFAULT_REPORT_INCHES 0 // false\n  #define DEFAULT_INVERT_ST_ENABLE 0 // false\n  #define DEFAULT_INVERT_LIMIT_PINS 0 // false  \n  #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false\n  #define DEFAULT_HARD_LIMIT_ENABLE 0  // false\n  #define DEFAULT_HOMING_ENABLE 0  // false\n  #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir\n  #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min\n  #define DEFAULT_HOMING_SEEK_RATE 250.0 // mm/min\n  #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)\n  #define DEFAULT_HOMING_PULLOFF 1.0 // mm  \n\n#endif\n"
  },
  {
    "path": "defaults/defaults_shapeoko2.h",
    "content": "/*\n  defaults_shapeoko2.h - defaults settings configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The defaults.h file serves as a central default settings file for different machine\n   types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings\n   here are supplied by users, so your results may vary. However, this should give you\n   a good starting point as you get to know your machine and tweak the settings for your\n   nefarious needs. */\n\n#ifndef defaults_h\n#define defaults_h\n\n  // Description: Shapeoko CNC mill with three NEMA 17 stepper motors, driven by Synthetos\n  // grblShield at 28V.\n  #define MICROSTEPS_XY 8\n  #define STEP_REVS_XY 200\n  #define MM_PER_REV_XY (2.0*20) // 2mm belt pitch, 20 pulley teeth\n  #define MICROSTEPS_Z 2\n  #define STEP_REVS_Z 200\n  #define MM_PER_REV_Z 1.250 // 1.25 mm/rev leadscrew\n  #define DEFAULT_X_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)\n  #define DEFAULT_Y_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)\n  #define DEFAULT_Z_STEPS_PER_MM (MICROSTEPS_Z*STEP_REVS_Z/MM_PER_REV_Z)\n  #define DEFAULT_X_MAX_RATE 5000.0 // mm/min\n  #define DEFAULT_Y_MAX_RATE 5000.0 // mm/min\n  #define DEFAULT_Z_MAX_RATE 500.0 // mm/min\n  #define DEFAULT_X_ACCELERATION (250.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2\n  #define DEFAULT_Y_ACCELERATION (250.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2\n  #define DEFAULT_Z_ACCELERATION (50.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2\n  #define DEFAULT_X_MAX_TRAVEL 290.0 // mm\n  #define DEFAULT_Y_MAX_TRAVEL 290.0 // mm\n  #define DEFAULT_Z_MAX_TRAVEL 100.0 // mm\n  #define DEFAULT_STEP_PULSE_MICROSECONDS 10\n  #define DEFAULT_STEPPING_INVERT_MASK 0\n  #define DEFAULT_DIRECTION_INVERT_MASK ((1<<X_AXIS)|(1<<Z_AXIS))\n  #define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)\n  #define DEFAULT_STATUS_REPORT_MASK ((BITFLAG_RT_STATUS_MACHINE_POSITION)|(BITFLAG_RT_STATUS_WORK_POSITION))\n  #define DEFAULT_JUNCTION_DEVIATION 0.02 // mm\n  #define DEFAULT_ARC_TOLERANCE 0.002 // mm\n  #define DEFAULT_REPORT_INCHES 0 // false\n  #define DEFAULT_INVERT_ST_ENABLE 0 // false\n  #define DEFAULT_INVERT_LIMIT_PINS 0 // false  \n  #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false\n  #define DEFAULT_HARD_LIMIT_ENABLE 0  // false\n  #define DEFAULT_HOMING_ENABLE 0  // false\n  #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir\n  #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min\n  #define DEFAULT_HOMING_SEEK_RATE 250.0 // mm/min\n  #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)\n  #define DEFAULT_HOMING_PULLOFF 1.0 // mm  \n\n#endif\n"
  },
  {
    "path": "defaults/defaults_shapeoko3.h",
    "content": "/*\n  defaults_shapeoko3.h - defaults settings configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The defaults.h file serves as a central default settings file for different machine\n   types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings\n   here are supplied by users, so your results may vary. However, this should give you\n   a good starting point as you get to know your machine and tweak the settings for your\n   nefarious needs. */\n\n#ifndef defaults_h\n#define defaults_h\n\n  // Description: Shapeoko CNC mill with three NEMA 23 stepper motors, driven by CarbideMotion\n  #define MICROSTEPS_XY 8\n  #define STEP_REVS_XY 200\n  #define MM_PER_REV_XY (2.0*20) // 2mm belt pitch, 20 pulley teeth\n  #define MICROSTEPS_Z 8\n  #define STEP_REVS_Z 200\n  #define MM_PER_REV_Z (2.0*20) // 2mm belt pitch, 20 pulley teeth\n  #define DEFAULT_X_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)\n  #define DEFAULT_Y_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)\n  #define DEFAULT_Z_STEPS_PER_MM (MICROSTEPS_Z*STEP_REVS_Z/MM_PER_REV_Z)\n  #define DEFAULT_X_MAX_RATE 5000.0 // mm/min\n  #define DEFAULT_Y_MAX_RATE 5000.0 // mm/min\n  #define DEFAULT_Z_MAX_RATE 5000.0 // mm/min\n  #define DEFAULT_X_ACCELERATION (400.0*60*60) // 400*60*60 mm/min^2 = 400 mm/sec^2\n  #define DEFAULT_Y_ACCELERATION (400.0*60*60) // 400*60*60 mm/min^2 = 400 mm/sec^2\n  #define DEFAULT_Z_ACCELERATION (400.0*60*60) // 400*60*60 mm/min^2 = 400 mm/sec^2\n  #define DEFAULT_X_MAX_TRAVEL 425.0 // mm\n  #define DEFAULT_Y_MAX_TRAVEL 465.0 // mm\n  #define DEFAULT_Z_MAX_TRAVEL 80.0 // mm\n  #define DEFAULT_STEP_PULSE_MICROSECONDS 10\n  #define DEFAULT_STEPPING_INVERT_MASK 0\n  #define DEFAULT_DIRECTION_INVERT_MASK ((1<<X_AXIS)|(1<<Z_AXIS))\n  #define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)\n  #define DEFAULT_STATUS_REPORT_MASK 255 // All enabled\n  #define DEFAULT_JUNCTION_DEVIATION 0.02 // mm\n  #define DEFAULT_ARC_TOLERANCE 0.01 // mm\n  #define DEFAULT_REPORT_INCHES 0 // false\n  #define DEFAULT_INVERT_ST_ENABLE 0 // false\n  #define DEFAULT_INVERT_LIMIT_PINS 0 // false  \n  #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false\n  #define DEFAULT_HARD_LIMIT_ENABLE 0  // false\n  #define DEFAULT_HOMING_ENABLE 0  // false\n  #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir\n  #define DEFAULT_HOMING_FEED_RATE 100.0 // mm/min\n  #define DEFAULT_HOMING_SEEK_RATE 1000.0 // mm/min\n  #define DEFAULT_HOMING_DEBOUNCE_DELAY 25 // msec (0-65k)\n  #define DEFAULT_HOMING_PULLOFF 5.0 // mm  \n\n#endif\n"
  },
  {
    "path": "defaults/defaults_sherline.h",
    "content": "/*\n  defaults_sherline.h - defaults settings configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The defaults.h file serves as a central default settings file for different machine\n   types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings\n   here are supplied by users, so your results may vary. However, this should give you\n   a good starting point as you get to know your machine and tweak the settings for your\n   nefarious needs. */\n\n#ifndef defaults_h\n#define defaults_h\n\n  // Description: Sherline 5400 mill with three NEMA 23 Keling  KL23H256-21-8B 185 oz-in stepper motors,\n  // driven by three Pololu A4988 stepper drivers with a 30V, 6A power supply at 1.5A per winding.\n  #define MICROSTEPS 2\n  #define STEPS_PER_REV 200.0\n  #define MM_PER_REV (0.050*MM_PER_INCH) // 0.050 inch/rev leadscrew\n  #define DEFAULT_X_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV)\n  #define DEFAULT_Y_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV)\n  #define DEFAULT_Z_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV)\n  #define DEFAULT_X_MAX_RATE 635.0 // mm/min (25 ipm)\n  #define DEFAULT_Y_MAX_RATE 635.0 // mm/min\n  #define DEFAULT_Z_MAX_RATE 635.0 // mm/min\n  #define DEFAULT_X_ACCELERATION (50.0*60*60) // 50*60*60 mm/min^2 = 50 mm/sec^2\n  #define DEFAULT_Y_ACCELERATION (50.0*60*60) // 50*60*60 mm/min^2 = 50 mm/sec^2\n  #define DEFAULT_Z_ACCELERATION (50.0*60*60) // 50*60*60 mm/min^2 = 50 mm/sec^2\n  #define DEFAULT_X_MAX_TRAVEL 225.0 // mm\n  #define DEFAULT_Y_MAX_TRAVEL 125.0 // mm\n  #define DEFAULT_Z_MAX_TRAVEL 170.0 // mm\n  #define DEFAULT_STEP_PULSE_MICROSECONDS 10\n  #define DEFAULT_STEPPING_INVERT_MASK 0\n  #define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_AXIS)|(1<<Z_AXIS))  \n  #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)\n  #define DEFAULT_STATUS_REPORT_MASK ((BITFLAG_RT_STATUS_MACHINE_POSITION)|(BITFLAG_RT_STATUS_WORK_POSITION))\n  #define DEFAULT_JUNCTION_DEVIATION 0.01 // mm\n  #define DEFAULT_ARC_TOLERANCE 0.002 // mm\n  #define DEFAULT_REPORT_INCHES 0 // true\n  #define DEFAULT_INVERT_ST_ENABLE 0 // false\n  #define DEFAULT_INVERT_LIMIT_PINS 0 // false\n  #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false\n  #define DEFAULT_HARD_LIMIT_ENABLE 0  // false\n  #define DEFAULT_HOMING_ENABLE 0  // false\n  #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir\n  #define DEFAULT_HOMING_FEED_RATE 50.0 // mm/min\n  #define DEFAULT_HOMING_SEEK_RATE 635.0 // mm/min\n  #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)\n  #define DEFAULT_HOMING_PULLOFF 1.0 // mm\n\n#endif\n"
  },
  {
    "path": "defaults/defaults_simulator.h",
    "content": "/*\n  defaults_simulator.h - defaults settings configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The defaults.h file serves as a central default settings file for different machine\n   types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings\n   here are supplied by users, so your results may vary. However, this should give you\n   a good starting point as you get to know your machine and tweak the settings for your\n   nefarious needs. */\n\n#ifndef defaults_h\n#define defaults_h\n\n  // Settings only for Grbl Simulator (www.github.com/grbl/grbl-sim)\n  // Grbl generic default settings. Should work across different machines.\n  #define DEFAULT_X_STEPS_PER_MM 1000.0\n  #define DEFAULT_Y_STEPS_PER_MM 1000.0\n  #define DEFAULT_Z_STEPS_PER_MM 1000.0\n  #define DEFAULT_X_MAX_RATE 1000.0 // mm/min\n  #define DEFAULT_Y_MAX_RATE 1000.0 // mm/min\n  #define DEFAULT_Z_MAX_RATE 1000.0 // mm/min\n  #define DEFAULT_X_ACCELERATION (100.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2\n  #define DEFAULT_Y_ACCELERATION (100.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2\n  #define DEFAULT_Z_ACCELERATION (100.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2\n  #define DEFAULT_X_MAX_TRAVEL 1000.0 // mm\n  #define DEFAULT_Y_MAX_TRAVEL 1000.0 // mm\n  #define DEFAULT_Z_MAX_TRAVEL 1000.0 // mm\n  #define DEFAULT_STEP_PULSE_MICROSECONDS 10\n  #define DEFAULT_STEPPING_INVERT_MASK 0\n  #define DEFAULT_DIRECTION_INVERT_MASK 0\n  #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)\n  #define DEFAULT_STATUS_REPORT_MASK ((BITFLAG_RT_STATUS_MACHINE_POSITION)|(BITFLAG_RT_STATUS_WORK_POSITION))\n  #define DEFAULT_JUNCTION_DEVIATION 0.01 // mm\n  #define DEFAULT_ARC_TOLERANCE 0.002 // mm\n  #define DEFAULT_REPORT_INCHES 0 // false\n  #define DEFAULT_INVERT_ST_ENABLE 0 // false\n  #define DEFAULT_INVERT_LIMIT_PINS 0 // false\n  #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false\n  #define DEFAULT_HARD_LIMIT_ENABLE 0  // false\n  #define DEFAULT_HOMING_ENABLE 0  // false\n  #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir\n  #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min\n  #define DEFAULT_HOMING_SEEK_RATE 500.0 // mm/min\n  #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)\n  #define DEFAULT_HOMING_PULLOFF 1.0 // mm\n\n#endif\n"
  },
  {
    "path": "defaults/defaults_x_carve_1000mm.h",
    "content": "/*\n  defaults_x_carve_1000mm.h - defaults settings configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The defaults.h file serves as a central default settings file for different machine\n   types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings\n   here are supplied by users, so your results may vary. However, this should give you\n   a good starting point as you get to know your machine and tweak the settings for your\n   nefarious needs. */\n\n#ifndef defaults_h\n#define defaults_h\n\n  // Description: X-Carve 3D Carver CNC mill with three 200 step/rev motors driven by Synthetos\n  // grblShield at 24V.\n  #define MICROSTEPS_XY 8\n  #define STEP_REVS_XY 200\n  #define MM_PER_REV_XY (2.0*20) // 2mm belt pitch, 20 pulley teeth\n  #define MICROSTEPS_Z 2\n  #define STEP_REVS_Z 200\n  #define MM_PER_REV_Z 2.117 // ACME 3/8-12 Leadscrew\n  #define DEFAULT_X_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)\n  #define DEFAULT_Y_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)\n  #define DEFAULT_Z_STEPS_PER_MM (MICROSTEPS_Z*STEP_REVS_Z/MM_PER_REV_Z)\n  #define DEFAULT_X_MAX_RATE 8000.0 // mm/min\n  #define DEFAULT_Y_MAX_RATE 8000.0 // mm/min\n  #define DEFAULT_Z_MAX_RATE 500.0 // mm/min\n  #define DEFAULT_X_ACCELERATION (500.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2\n  #define DEFAULT_Y_ACCELERATION (500.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2\n  #define DEFAULT_Z_ACCELERATION (50.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2\n  #define DEFAULT_X_MAX_TRAVEL 740.0 // mm\n  #define DEFAULT_Y_MAX_TRAVEL 790.0 // mm\n  #define DEFAULT_Z_MAX_TRAVEL 100.0 // mm\n  #define DEFAULT_STEP_PULSE_MICROSECONDS 10\n  #define DEFAULT_STEPPING_INVERT_MASK 0\n  #define DEFAULT_DIRECTION_INVERT_MASK ((1<<X_AXIS)|(1<<Y_AXIS))\n  #define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)\n  #define DEFAULT_STATUS_REPORT_MASK ((BITFLAG_RT_STATUS_MACHINE_POSITION)|(BITFLAG_RT_STATUS_WORK_POSITION))\n  #define DEFAULT_JUNCTION_DEVIATION 0.02 // mm\n  #define DEFAULT_ARC_TOLERANCE 0.002 // mm\n  #define DEFAULT_REPORT_INCHES 0 // false\n  #define DEFAULT_INVERT_ST_ENABLE 0 // false\n  #define DEFAULT_INVERT_LIMIT_PINS 0 // false  \n  #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false\n  #define DEFAULT_HARD_LIMIT_ENABLE 0  // false\n  #define DEFAULT_HOMING_ENABLE 0  // false\n  #define DEFAULT_HOMING_DIR_MASK 3 // move positive dir\n  #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min\n  #define DEFAULT_HOMING_SEEK_RATE 750.0 // mm/min\n  #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)\n  #define DEFAULT_HOMING_PULLOFF 1.0 // mm \n  \n#endif\n "
  },
  {
    "path": "defaults/defaults_x_carve_500mm.h",
    "content": "/*\n  defaults_x_carve_500mm.h - defaults settings configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The defaults.h file serves as a central default settings file for different machine\n   types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings\n   here are supplied by users, so your results may vary. However, this should give you\n   a good starting point as you get to know your machine and tweak the settings for your\n   nefarious needs. */\n\n#ifndef defaults_h\n#define defaults_h\n\n  // Description: X-Carve 3D Carver CNC mill with three 200 step/rev motors driven by Synthetos\n  // grblShield at 24V.\n  #define MICROSTEPS_XY 8\n  #define STEP_REVS_XY 200\n  #define MM_PER_REV_XY (2.0*20) // 2mm belt pitch, 20 pulley teeth\n  #define MICROSTEPS_Z 2\n  #define STEP_REVS_Z 200\n  #define MM_PER_REV_Z 2.117 // ACME 3/8-12 Leadscrew\n  #define DEFAULT_X_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)\n  #define DEFAULT_Y_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)\n  #define DEFAULT_Z_STEPS_PER_MM (MICROSTEPS_Z*STEP_REVS_Z/MM_PER_REV_Z)\n  #define DEFAULT_X_MAX_RATE 8000.0 // mm/min\n  #define DEFAULT_Y_MAX_RATE 8000.0 // mm/min\n  #define DEFAULT_Z_MAX_RATE 500.0 // mm/min\n  #define DEFAULT_X_ACCELERATION (500.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2\n  #define DEFAULT_Y_ACCELERATION (500.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2\n  #define DEFAULT_Z_ACCELERATION (50.0*60*60) // 25*60*60 mm/min^2 = 25 mm/sec^2\n  #define DEFAULT_X_MAX_TRAVEL 290.0 // mm\n  #define DEFAULT_Y_MAX_TRAVEL 290.0 // mm\n  #define DEFAULT_Z_MAX_TRAVEL 100.0 // mm\n  #define DEFAULT_STEP_PULSE_MICROSECONDS 10\n  #define DEFAULT_STEPPING_INVERT_MASK 0\n  #define DEFAULT_DIRECTION_INVERT_MASK ((1<<X_AXIS)|(1<<Y_AXIS))\n  #define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)\n  #define DEFAULT_STATUS_REPORT_MASK ((BITFLAG_RT_STATUS_MACHINE_POSITION)|(BITFLAG_RT_STATUS_WORK_POSITION))\n  #define DEFAULT_JUNCTION_DEVIATION 0.02 // mm\n  #define DEFAULT_ARC_TOLERANCE 0.002 // mm\n  #define DEFAULT_REPORT_INCHES 0 // false\n  #define DEFAULT_INVERT_ST_ENABLE 0 // false\n  #define DEFAULT_INVERT_LIMIT_PINS 0 // false  \n  #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false\n  #define DEFAULT_HARD_LIMIT_ENABLE 0  // false\n  #define DEFAULT_HOMING_ENABLE 0  // false\n  #define DEFAULT_HOMING_DIR_MASK 3 // move positive dir\n  #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min\n  #define DEFAULT_HOMING_SEEK_RATE 750.0 // mm/min\n  #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)\n  #define DEFAULT_HOMING_PULLOFF 1.0 // mm  \n  \n#endif\n "
  },
  {
    "path": "defaults/defaults_zen_toolworks_7x7.h",
    "content": "/*\n  defaults_zen_toolworks_7x7.h - defaults settings configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The defaults.h file serves as a central default settings file for different machine\n   types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings\n   here are supplied by users, so your results may vary. However, this should give you\n   a good starting point as you get to know your machine and tweak the settings for your\n   nefarious needs. */\n\n#ifndef defaults_h\n#define defaults_h\n\n  // Description: Zen Toolworks 7x7 mill with three Shinano SST43D2121 65oz-in NEMA 17 stepper motors.\n  // Leadscrew is different from some ZTW kits, where most are 1.25mm/rev rather than 8.0mm/rev here.\n  // Driven by 30V, 6A power supply and TI DRV8811 stepper motor drivers.\n  #define MICROSTEPS 8\n  #define STEPS_PER_REV 200.0\n  #define MM_PER_REV 8.0 // 8 mm/rev leadscrew\n  #define DEFAULT_X_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV)\n  #define DEFAULT_Y_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV)\n  #define DEFAULT_Z_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV)\n  #define DEFAULT_X_MAX_RATE 6000.0 // mm/min\n  #define DEFAULT_Y_MAX_RATE 6000.0 // mm/min\n  #define DEFAULT_Z_MAX_RATE 6000.0 // mm/min\n  #define DEFAULT_X_ACCELERATION (600.0*60*60) // 600*60*60 mm/min^2 = 600 mm/sec^2\n  #define DEFAULT_Y_ACCELERATION (600.0*60*60) // 600*60*60 mm/min^2 = 600 mm/sec^2\n  #define DEFAULT_Z_ACCELERATION (600.0*60*60) // 600*60*60 mm/min^2 = 600 mm/sec^2\n  #define DEFAULT_X_MAX_TRAVEL 190.0 // mm\n  #define DEFAULT_Y_MAX_TRAVEL 180.0 // mm\n  #define DEFAULT_Z_MAX_TRAVEL 150.0 // mm\n  #define DEFAULT_STEP_PULSE_MICROSECONDS 10\n  #define DEFAULT_STEPPING_INVERT_MASK 0\n  #define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_AXIS))  \n  #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)\n  #define DEFAULT_STATUS_REPORT_MASK ((BITFLAG_RT_STATUS_MACHINE_POSITION)|(BITFLAG_RT_STATUS_WORK_POSITION))\n  #define DEFAULT_JUNCTION_DEVIATION 0.02 // mm\n  #define DEFAULT_ARC_TOLERANCE 0.002 // mm\n  #define DEFAULT_REPORT_INCHES 0 // false\n  #define DEFAULT_INVERT_ST_ENABLE 0 // false\n  #define DEFAULT_INVERT_LIMIT_PINS 0 // false  \n  #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false\n  #define DEFAULT_HARD_LIMIT_ENABLE 0  // false\n  #define DEFAULT_HOMING_ENABLE 0  // false\n  #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir\n  #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min\n  #define DEFAULT_HOMING_SEEK_RATE 250.0 // mm/min\n  #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)\n  #define DEFAULT_HOMING_PULLOFF 1.0 // mm\n\n#endif\n\n"
  },
  {
    "path": "defaults.h",
    "content": "/*\n  defaults.h - defaults settings configuration file\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* The defaults.h file serves as a central default settings selector for different machine\n   types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings \n   files listed here are supplied by users, so your results may vary. However, this should\n   give you a good starting point as you get to know your machine and tweak the settings for\n   your nefarious needs.\n   Ensure one and only one of these DEFAULTS_XXX values is defined in config.h */\n\n#ifndef defaults_h\n\n// Only define the DEFAULT_XXX with where to find the corresponding default_XXX.h file.\n// Don't #define defaults_h here, let the selected file do it. Prevents including more than one.\n\n#ifdef DEFAULTS_GENERIC\n  // Grbl generic default settings. Should work across different machines.\n  #include \"defaults/defaults_generic.h\"\n#endif\n\n#ifdef DEFAULTS_SHERLINE_5400\n  // Description: Sherline 5400 mill with three NEMA 23 Keling  KL23H256-21-8B 185 oz-in stepper motors,\n  // driven by three Pololu A4988 stepper drivers with a 30V, 6A power supply at 1.5A per winding.\n  #include \"defaults/defaults_sherline.h\"\n#endif\n\n#ifdef DEFAULTS_SHAPEOKO\n  // Description: Shapeoko CNC mill with three NEMA 17 stepper motors, driven by Synthetos\n  // grblShield with a 24V, 4.2A power supply.\n  #include \"defaults/defaults_shapeoko.h\"\n#endif\n\n#ifdef DEFAULTS_SHAPEOKO_2\n  // Description: Shapeoko CNC mill with three NEMA 17 stepper motors, driven by Synthetos\n  // grblShield at 28V.\n  #include \"defaults/defaults_shapeoko2.h\"\n#endif\n\n#ifdef DEFAULTS_SHAPEOKO_3\n  // Description: Shapeoko CNC mill with three NEMA 23 stepper motors, driven by CarbideMotion\n  #include \"defaults/defaults_shapeoko3.h\"\n#endif\n\n#ifdef DEFAULTS_X_CARVE_500MM\n  // Description: X-Carve 3D Carver CNC mill with three 200 step/rev motors driven by Synthetos\n  // grblShield at 24V.\n  #include \"defaults/defaults_x_carve_500mm.h\"\n#endif\n\n#ifdef DEFAULTS_X_CARVE_1000MM\n  // Description: X-Carve 3D Carver CNC mill with three 200 step/rev motors driven by Synthetos\n  // grblShield at 24V.\n  #include \"defaults/defaults_x_carve_1000mm.h\"\n#endif\n\n#ifdef DEFAULTS_ZEN_TOOLWORKS_7x7\n  // Description: Zen Toolworks 7x7 mill with three Shinano SST43D2121 65oz-in NEMA 17 stepper motors.\n  // Leadscrew is different from some ZTW kits, where most are 1.25mm/rev rather than 8.0mm/rev here.\n  // Driven by 30V, 6A power supply and TI DRV8811 stepper motor drivers.\n  #include \"defaults/defaults_zen_toolworks_7x7.h\"\n#endif\n\n#ifdef DEFAULTS_OXCNC\n  // Grbl settings for OpenBuilds OX CNC Machine\n  // http://www.openbuilds.com/builds/openbuilds-ox-cnc-machine.341/\n  #include \"defaults/defaults_oxcnc.h\"\n#endif\n\n#ifdef DEFAULTS_SIMULATOR\n  // Settings only for Grbl Simulator (www.github.com/grbl/grbl-sim)\n  #include \"defaults/defaults_simulator.h\"\n#endif\n\n#endif\n"
  },
  {
    "path": "eeprom.c",
    "content": "// This file has been prepared for Doxygen automatic documentation generation.\n/*! \\file ********************************************************************\n*\n* Atmel Corporation\n*\n* \\li File:               eeprom.c\n* \\li Compiler:           IAR EWAAVR 3.10c\n* \\li Support mail:       avr@atmel.com\n*\n* \\li Supported devices:  All devices with split EEPROM erase/write\n*                         capabilities can be used.\n*                         The example is written for ATmega48.\n*\n* \\li AppNote:            AVR103 - Using the EEPROM Programming Modes.\n*\n* \\li Description:        Example on how to use the split EEPROM erase/write\n*                         capabilities in e.g. ATmega48. All EEPROM\n*                         programming modes are tested, i.e. Erase+Write,\n*                         Erase-only and Write-only.\n*\n*                         $Revision: 1.6 $\n*                         $Date: Friday, February 11, 2005 07:16:44 UTC $\n****************************************************************************/\n#include <avr/io.h>\n#include <avr/interrupt.h>\n\n/* These EEPROM bits have different names on different devices. */\n#ifndef EEPE\n\t\t#define EEPE  EEWE  //!< EEPROM program/write enable.\n\t\t#define EEMPE EEMWE //!< EEPROM master program/write enable.\n#endif\n\n/* These two are unfortunately not defined in the device include files. */\n#define EEPM1 5 //!< EEPROM Programming Mode Bit 1.\n#define EEPM0 4 //!< EEPROM Programming Mode Bit 0.\n\n/* Define to reduce code size. */\n#define EEPROM_IGNORE_SELFPROG //!< Remove SPM flag polling.\n\n/*! \\brief  Read byte from EEPROM.\n *\n *  This function reads one byte from a given EEPROM address.\n *\n *  \\note  The CPU is halted for 4 clock cycles during EEPROM read.\n *\n *  \\param  addr  EEPROM address to read from.\n *  \\return  The byte read from the EEPROM address.\n */\nunsigned char eeprom_get_char( unsigned int addr )\n{\n\tdo {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.\n\tEEAR = addr; // Set EEPROM address register.\n\tEECR = (1<<EERE); // Start EEPROM read operation.\n\treturn EEDR; // Return the byte read from EEPROM.\n}\n\n/*! \\brief  Write byte to EEPROM.\n *\n *  This function writes one byte to a given EEPROM address.\n *  The differences between the existing byte and the new value is used\n *  to select the most efficient EEPROM programming mode.\n *\n *  \\note  The CPU is halted for 2 clock cycles during EEPROM programming.\n *\n *  \\note  When this function returns, the new EEPROM value is not available\n *         until the EEPROM programming time has passed. The EEPE bit in EECR\n *         should be polled to check whether the programming is finished.\n *\n *  \\note  The EEPROM_GetChar() function checks the EEPE bit automatically.\n *\n *  \\param  addr  EEPROM address to write to.\n *  \\param  new_value  New EEPROM value.\n */\nvoid eeprom_put_char( unsigned int addr, unsigned char new_value )\n{\n\tchar old_value; // Old EEPROM value.\n\tchar diff_mask; // Difference mask, i.e. old value XOR new value.\n\n\tcli(); // Ensure atomic operation for the write operation.\n\t\n\tdo {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.\n\t#ifndef EEPROM_IGNORE_SELFPROG\n\tdo {} while( SPMCSR & (1<<SELFPRGEN) ); // Wait for completion of SPM.\n\t#endif\n\t\n\tEEAR = addr; // Set EEPROM address register.\n\tEECR = (1<<EERE); // Start EEPROM read operation.\n\told_value = EEDR; // Get old EEPROM value.\n\tdiff_mask = old_value ^ new_value; // Get bit differences.\n\t\n\t// Check if any bits are changed to '1' in the new value.\n\tif( diff_mask & new_value ) {\n\t\t// Now we know that _some_ bits need to be erased to '1'.\n\t\t\n\t\t// Check if any bits in the new value are '0'.\n\t\tif( new_value != 0xff ) {\n\t\t\t// Now we know that some bits need to be programmed to '0' also.\n\t\t\t\n\t\t\tEEDR = new_value; // Set EEPROM data register.\n\t\t\tEECR = (1<<EEMPE) | // Set Master Write Enable bit...\n\t\t\t       (0<<EEPM1) | (0<<EEPM0); // ...and Erase+Write mode.\n\t\t\tEECR |= (1<<EEPE);  // Start Erase+Write operation.\n\t\t} else {\n\t\t\t// Now we know that all bits should be erased.\n\n\t\t\tEECR = (1<<EEMPE) | // Set Master Write Enable bit...\n\t\t\t       (1<<EEPM0);  // ...and Erase-only mode.\n\t\t\tEECR |= (1<<EEPE);  // Start Erase-only operation.\n\t\t}\n\t} else {\n\t\t// Now we know that _no_ bits need to be erased to '1'.\n\t\t\n\t\t// Check if any bits are changed from '1' in the old value.\n\t\tif( diff_mask ) {\n\t\t\t// Now we know that _some_ bits need to the programmed to '0'.\n\t\t\t\n\t\t\tEEDR = new_value;   // Set EEPROM data register.\n\t\t\tEECR = (1<<EEMPE) | // Set Master Write Enable bit...\n\t\t\t       (1<<EEPM1);  // ...and Write-only mode.\n\t\t\tEECR |= (1<<EEPE);  // Start Write-only operation.\n\t\t}\n\t}\n\t\n\tsei(); // Restore interrupt flag state.\n}\n\n// Extensions added as part of Grbl \n\n\nvoid memcpy_to_eeprom_with_checksum(unsigned int destination, char *source, unsigned int size) {\n  unsigned char checksum = 0;\n  for(; size > 0; size--) { \n    checksum = (checksum << 1) || (checksum >> 7);\n    checksum += *source;\n    eeprom_put_char(destination++, *(source++)); \n  }\n  eeprom_put_char(destination, checksum);\n}\n\nint memcpy_from_eeprom_with_checksum(char *destination, unsigned int source, unsigned int size) {\n  unsigned char data, checksum = 0;\n  for(; size > 0; size--) { \n    data = eeprom_get_char(source++);\n    checksum = (checksum << 1) || (checksum >> 7);\n    checksum += data;    \n    *(destination++) = data; \n  }\n  return(checksum == eeprom_get_char(source));\n}\n\n// end of file\n"
  },
  {
    "path": "eeprom.h",
    "content": "/*\n  eeprom.h - EEPROM methods\n  Part of Grbl\n\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef eeprom_h\n#define eeprom_h\n\nunsigned char eeprom_get_char(unsigned int addr);\nvoid eeprom_put_char(unsigned int addr, unsigned char new_value);\nvoid memcpy_to_eeprom_with_checksum(unsigned int destination, char *source, unsigned int size);\nint memcpy_from_eeprom_with_checksum(char *destination, unsigned int source, unsigned int size);\n\n#endif\n"
  },
  {
    "path": "examples/grblUpload/grblUpload.ino",
    "content": "/***********************************************************************\nThis sketch compiles and uploads Grbl to your 328p-based Arduino! \n\nTo use:\n- First make sure you have imported Grbl source code into your Arduino\n  IDE. There are details on our Github website on how to do this.\n\n- Select your Arduino Board and Serial Port in the Tools drop-down menu.\n  NOTE: Grbl only officially supports 328p-based Arduinos, like the Uno.\n  Using other boards will likely not work!\n\n- Then just click 'Upload'. That's it!\n\nFor advanced users:\n  If you'd like to see what else Grbl can do, there are some additional\n  options for customization and features you can enable or disable. \n  Navigate your file system to where the Arduino IDE has stored the Grbl \n  source code files, open the 'config.h' file in your favorite text \n  editor. Inside are dozens of feature descriptions and #defines. Simply\n  comment or uncomment the #defines or alter their assigned values, save\n  your changes, and then click 'Upload' here. \n\nCopyright (c) 2015 Sungeun K. Jeon\nReleased under the MIT-license. See license.txt for details.\n***********************************************************************/\n\n#include <grbl.h>\n\n// Do not alter this file!\n"
  },
  {
    "path": "examples/grblUpload/license.txt",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Sungeun K. Jeon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "gcode.c",
    "content": "/*\n  gcode.c - rs274/ngc parser.\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"grbl.h\"\n\n// NOTE: Max line number is defined by the g-code standard to be 99999. It seems to be an\n// arbitrary value, and some GUIs may require more. So we increased it based on a max safe\n// value when converting a float (7.2 digit precision)s to an integer.\n#define MAX_LINE_NUMBER 9999999 \n\n#define AXIS_COMMAND_NONE 0\n#define AXIS_COMMAND_NON_MODAL 1 \n#define AXIS_COMMAND_MOTION_MODE 2\n#define AXIS_COMMAND_TOOL_LENGTH_OFFSET 3 // *Undefined but required\n\n// Declare gc extern struct\nparser_state_t gc_state;\nparser_block_t gc_block;\n\n#define FAIL(status) return(status);\n\n\nvoid gc_init() \n{\n  memset(&gc_state, 0, sizeof(gc_state));\n  \n  // Load default G54 coordinate system.\n  if (!(settings_read_coord_data(gc_state.modal.coord_select,gc_state.coord_system))) { \n    report_status_message(STATUS_SETTING_READ_FAIL); \n  } \n}\n\n\n// Sets g-code parser position in mm. Input in steps. Called by the system abort and hard\n// limit pull-off routines.\nvoid gc_sync_position() \n{\n  system_convert_array_steps_to_mpos(gc_state.position,sys.position);\n}\n\n\nstatic uint8_t gc_check_same_position(float *pos_a, float *pos_b) \n{\n  uint8_t idx;\n  for (idx=0; idx<N_AXIS; idx++) {\n    if (pos_a[idx] != pos_b[idx]) { return(false); }\n  }\n  return(true);\n}\n         \n// Executes one line of 0-terminated G-Code. The line is assumed to contain only uppercase\n// characters and signed floating point values (no whitespace). Comments and block delete\n// characters have been removed. In this function, all units and positions are converted and \n// exported to grbl's internal functions in terms of (mm, mm/min) and absolute machine \n// coordinates, respectively.\nuint8_t gc_execute_line(char *line) \n{\n  /* -------------------------------------------------------------------------------------\n     STEP 1: Initialize parser block struct and copy current g-code state modes. The parser\n     updates these modes and commands as the block line is parser and will only be used and\n     executed after successful error-checking. The parser block struct also contains a block\n     values struct, word tracking variables, and a non-modal commands tracker for the new \n     block. This struct contains all of the necessary information to execute the block. */\n     \n  memset(&gc_block, 0, sizeof(gc_block)); // Initialize the parser block struct.\n  memcpy(&gc_block.modal,&gc_state.modal,sizeof(gc_modal_t)); // Copy current modes\n  uint8_t axis_command = AXIS_COMMAND_NONE;\n  uint8_t axis_0, axis_1, axis_linear;\n  uint8_t coord_select = 0; // Tracks G10 P coordinate selection for execution\n  float coordinate_data[N_AXIS]; // Multi-use variable to store coordinate data for execution\n  float parameter_data[N_AXIS]; // Multi-use variable to store parameter data for execution\n  \n  // Initialize bitflag tracking variables for axis indices compatible operations.\n  uint8_t axis_words = 0; // XYZ tracking\n  uint8_t ijk_words = 0; // IJK tracking \n\n  // Initialize command and value words variables. Tracks words contained in this block.\n  uint16_t command_words = 0; // G and M command words. Also used for modal group violations.\n  uint16_t value_words = 0; // Value words. \n\n  /* -------------------------------------------------------------------------------------\n     STEP 2: Import all g-code words in the block line. A g-code word is a letter followed by\n     a number, which can either be a 'G'/'M' command or sets/assigns a command value. Also, \n     perform initial error-checks for command word modal group violations, for any repeated\n     words, and for negative values set for the value words F, N, P, T, and S. */\n     \n  uint8_t word_bit; // Bit-value for assigning tracking variables\n  uint8_t char_counter = 0;  \n  char letter;\n  float value;\n  uint8_t int_value = 0;\n  uint16_t mantissa = 0;\n\n  while (line[char_counter] != 0) { // Loop until no more g-code words in line.\n    \n    // Import the next g-code word, expecting a letter followed by a value. Otherwise, error out.\n    letter = line[char_counter];\n    if((letter < 'A') || (letter > 'Z')) { FAIL(STATUS_EXPECTED_COMMAND_LETTER); } // [Expected word letter]\n    char_counter++;\n    if (!read_float(line, &char_counter, &value)) { FAIL(STATUS_BAD_NUMBER_FORMAT); } // [Expected word value]\n\n    // Convert values to smaller uint8 significand and mantissa values for parsing this word.\n    // NOTE: Mantissa is multiplied by 100 to catch non-integer command values. This is more \n    // accurate than the NIST gcode requirement of x10 when used for commands, but not quite\n    // accurate enough for value words that require integers to within 0.0001. This should be\n    // a good enough comprimise and catch most all non-integer errors. To make it compliant, \n    // we would simply need to change the mantissa to int16, but this add compiled flash space.\n    // Maybe update this later. \n    int_value = trunc(value);\n    mantissa =  round(100*(value - int_value)); // Compute mantissa for Gxx.x commands.\n        // NOTE: Rounding must be used to catch small floating point errors. \n\n    // Check if the g-code word is supported or errors due to modal group violations or has\n    // been repeated in the g-code block. If ok, update the command or record its value.\n    switch(letter) {\n    \n      /* 'G' and 'M' Command Words: Parse commands and check for modal group violations.\n         NOTE: Modal group numbers are defined in Table 4 of NIST RS274-NGC v3, pg.20 */\n         \n      case 'G':\n        // Determine 'G' command and its modal group\n        switch(int_value) {\n          case 10: case 28: case 30: case 92: \n            // Check for G10/28/30/92 being called with G0/1/2/3/38 on same block.\n            // * G43.1 is also an axis command but is not explicitly defined this way.\n            if (mantissa == 0) { // Ignore G28.1, G30.1, and G92.1\n              if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]\n              axis_command = AXIS_COMMAND_NON_MODAL;\n            }\n            // No break. Continues to next line.\n          case 4: case 53: \n            word_bit = MODAL_GROUP_G0; \n            switch(int_value) {\n              case 4: gc_block.non_modal_command = NON_MODAL_DWELL; break; // G4\n              case 10: gc_block.non_modal_command = NON_MODAL_SET_COORDINATE_DATA; break; // G10\n              case 28:\n                switch(mantissa) {\n                  case 0: gc_block.non_modal_command = NON_MODAL_GO_HOME_0; break;  // G28\n                  case 10: gc_block.non_modal_command = NON_MODAL_SET_HOME_0; break; // G28.1\n                  default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G28.x command]\n                }\n                mantissa = 0; // Set to zero to indicate valid non-integer G command.\n                break;\n              case 30: \n                switch(mantissa) {\n                  case 0: gc_block.non_modal_command = NON_MODAL_GO_HOME_1; break;  // G30\n                  case 10: gc_block.non_modal_command = NON_MODAL_SET_HOME_1; break; // G30.1\n                  default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G30.x command]\n                }\n                mantissa = 0; // Set to zero to indicate valid non-integer G command.\n                break;\n              case 53: gc_block.non_modal_command = NON_MODAL_ABSOLUTE_OVERRIDE; break; // G53\n              case 92: \n                switch(mantissa) {\n                  case 0: gc_block.non_modal_command = NON_MODAL_SET_COORDINATE_OFFSET; break; // G92\n                  case 10: gc_block.non_modal_command = NON_MODAL_RESET_COORDINATE_OFFSET; break; // G92.1\n                  default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G92.x command]\n                }\n                mantissa = 0; // Set to zero to indicate valid non-integer G command.\n                break;      \n            }\n            break;\n          case 0: case 1: case 2: case 3: case 38: \n            // Check for G0/1/2/3/38 being called with G10/28/30/92 on same block.\n            // * G43.1 is also an axis command but is not explicitly defined this way.\n            if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]\n            axis_command = AXIS_COMMAND_MOTION_MODE; \n            // No break. Continues to next line.\n          case 80: \n            word_bit = MODAL_GROUP_G1; \n            switch(int_value) {\n              case 0: gc_block.modal.motion = MOTION_MODE_SEEK; break; // G0\n              case 1: gc_block.modal.motion = MOTION_MODE_LINEAR; break; // G1\n              case 2: gc_block.modal.motion = MOTION_MODE_CW_ARC; break; // G2\n              case 3: gc_block.modal.motion = MOTION_MODE_CCW_ARC; break; // G3\n              case 38: \n                switch(mantissa) {\n                  case 20: gc_block.modal.motion = MOTION_MODE_PROBE_TOWARD; break; // G38.2\n                  case 30: gc_block.modal.motion = MOTION_MODE_PROBE_TOWARD_NO_ERROR; break; // G38.3\n                  case 40: gc_block.modal.motion = MOTION_MODE_PROBE_AWAY; break; // G38.4\n                  case 50: gc_block.modal.motion = MOTION_MODE_PROBE_AWAY_NO_ERROR; break; // G38.5\n                  default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G38.x command]\n                }\n                mantissa = 0; // Set to zero to indicate valid non-integer G command.\n                break;\n              case 80: gc_block.modal.motion = MOTION_MODE_NONE; break; // G80\n            }            \n            break;\n          case 17: case 18: case 19: \n            word_bit = MODAL_GROUP_G2; \n            switch(int_value) {\n              case 17: gc_block.modal.plane_select = PLANE_SELECT_XY; break;\n              case 18: gc_block.modal.plane_select = PLANE_SELECT_ZX; break;\n              case 19: gc_block.modal.plane_select = PLANE_SELECT_YZ; break;\n            }\n            break;\n          case 90: case 91: \n            if (mantissa == 0) {\n              word_bit = MODAL_GROUP_G3; \n              if (int_value == 90) { gc_block.modal.distance = DISTANCE_MODE_ABSOLUTE; } // G90\n              else { gc_block.modal.distance = DISTANCE_MODE_INCREMENTAL; } // G91\n            } else {\n              word_bit = MODAL_GROUP_G4;\n              if ((mantissa != 10) || (int_value == 90)) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G90.1 not supported]\n              mantissa = 0; // Set to zero to indicate valid non-integer G command.\n              // Otherwise, arc IJK incremental mode is default. G91.1 does nothing.\n            }\n            break;\n          case 93: case 94: \n            word_bit = MODAL_GROUP_G5; \n            if (int_value == 93) { gc_block.modal.feed_rate = FEED_RATE_MODE_INVERSE_TIME; } // G93\n            else { gc_block.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN; } // G94\n            break;\n          case 20: case 21: \n            word_bit = MODAL_GROUP_G6; \n            if (int_value == 20) { gc_block.modal.units = UNITS_MODE_INCHES; }  // G20\n            else { gc_block.modal.units = UNITS_MODE_MM; } // G21\n            break;\n          case 40:\n            word_bit = MODAL_GROUP_G7;\n            // NOTE: Not required since cutter radius compensation is always disabled. Only here\n            // to support G40 commands that often appear in g-code program headers to setup defaults.\n            // gc_block.modal.cutter_comp = CUTTER_COMP_DISABLE; // G40\n            break;\n          case 43: case 49:\n            word_bit = MODAL_GROUP_G8;\n            // NOTE: The NIST g-code standard vaguely states that when a tool length offset is changed,\n            // there cannot be any axis motion or coordinate offsets updated. Meaning G43, G43.1, and G49\n            // all are explicit axis commands, regardless if they require axis words or not. \n            if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict] }\n            axis_command = AXIS_COMMAND_TOOL_LENGTH_OFFSET;\n            if (int_value == 49) { // G49\n              gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_CANCEL; \n            } else if (mantissa == 10) { // G43.1\n              gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC;\n            } else { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [Unsupported G43.x command]\n            mantissa = 0; // Set to zero to indicate valid non-integer G command.\n            break;\n          case 54: case 55: case 56: case 57: case 58: case 59: \n            // NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.)\n            word_bit = MODAL_GROUP_G12;\n            gc_block.modal.coord_select = int_value-54; // Shift to array indexing.\n            break;\n          case 61:\n            word_bit = MODAL_GROUP_G13;\n            if (mantissa != 0) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G61.1 not supported]\n            // gc_block.modal.control = CONTROL_MODE_EXACT_PATH; // G61\n            break;\n          default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G command]\n        }      \n        if (mantissa > 0) { FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); } // [Unsupported or invalid Gxx.x command]\n        // Check for more than one command per modal group violations in the current block\n        // NOTE: Variable 'word_bit' is always assigned, if the command is valid.\n        if ( bit_istrue(command_words,bit(word_bit)) ) { FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); }\n        command_words |= bit(word_bit);\n        break;\n        \n      case 'M':\n      \n        // Determine 'M' command and its modal group\n        if (mantissa > 0) { FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); } // [No Mxx.x commands]\n        switch(int_value) {\n          case 0: case 1: case 2: case 30: \n            word_bit = MODAL_GROUP_M4; \n            switch(int_value) {\n              case 0: gc_block.modal.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause\n              case 1: break; // Optional stop not supported. Ignore.\n              case 2: case 30: gc_block.modal.program_flow = PROGRAM_FLOW_COMPLETED; break; // Program end and reset \n            }\n            break;\n          #ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN\n            case 4: \n          #endif\n          case 3: case 5:\n            word_bit = MODAL_GROUP_M7; \n            switch(int_value) {\n              case 3: gc_block.modal.spindle = SPINDLE_ENABLE_CW; break;\n              #ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN\n                case 4: gc_block.modal.spindle = SPINDLE_ENABLE_CCW; break;\n              #endif\n              case 5: gc_block.modal.spindle = SPINDLE_DISABLE; break;\n            }\n            break;            \n         #ifdef ENABLE_M7  \n          case 7:\n         #endif\n          case 8: case 9:\n            word_bit = MODAL_GROUP_M8; \n            switch(int_value) {      \n             #ifdef ENABLE_M7\n              case 7: gc_block.modal.coolant = COOLANT_MIST_ENABLE; break;\n             #endif\n              case 8: gc_block.modal.coolant = COOLANT_FLOOD_ENABLE; break;\n              case 9: gc_block.modal.coolant = COOLANT_DISABLE; break;\n            }\n            break;\n          default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported M command]\n        }\n      \n        // Check for more than one command per modal group violations in the current block\n        // NOTE: Variable 'word_bit' is always assigned, if the command is valid.\n        if ( bit_istrue(command_words,bit(word_bit)) ) { FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); }\n        command_words |= bit(word_bit);\n        break;\n      \n      // NOTE: All remaining letters assign values.\n      default: \n  \n        /* Non-Command Words: This initial parsing phase only checks for repeats of the remaining\n           legal g-code words and stores their value. Error-checking is performed later since some\n           words (I,J,K,L,P,R) have multiple connotations and/or depend on the issued commands. */\n        switch(letter){\n          // case 'A': // Not supported\n          // case 'B': // Not supported\n          // case 'C': // Not supported\n          // case 'D': // Not supported\n          case 'F': word_bit = WORD_F; gc_block.values.f = value; break;\n          // case 'H': // Not supported\n          case 'I': word_bit = WORD_I; gc_block.values.ijk[X_AXIS] = value; ijk_words |= (1<<X_AXIS); break;\n          case 'J': word_bit = WORD_J; gc_block.values.ijk[Y_AXIS] = value; ijk_words |= (1<<Y_AXIS); break;\n          case 'K': word_bit = WORD_K; gc_block.values.ijk[Z_AXIS] = value; ijk_words |= (1<<Z_AXIS); break;\n          case 'L': word_bit = WORD_L; gc_block.values.l = int_value; break;\n          case 'N': word_bit = WORD_N; gc_block.values.n = trunc(value); break;\n          case 'P': word_bit = WORD_P; gc_block.values.p = value; break;\n          // NOTE: For certain commands, P value must be an integer, but none of these commands are supported.\n          // case 'Q': // Not supported\n          case 'R': word_bit = WORD_R; gc_block.values.r = value; break;\n          case 'S': word_bit = WORD_S; gc_block.values.s = value; break;\n          case 'T': word_bit = WORD_T; break; // gc.values.t = int_value;\n          case 'X': word_bit = WORD_X; gc_block.values.xyz[X_AXIS] = value; axis_words |= (1<<X_AXIS); break;\n          case 'Y': word_bit = WORD_Y; gc_block.values.xyz[Y_AXIS] = value; axis_words |= (1<<Y_AXIS); break;\n          case 'Z': word_bit = WORD_Z; gc_block.values.xyz[Z_AXIS] = value; axis_words |= (1<<Z_AXIS); break;\n          default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND);\n        } \n        \n        // NOTE: Variable 'word_bit' is always assigned, if the non-command letter is valid.\n        if (bit_istrue(value_words,bit(word_bit))) { FAIL(STATUS_GCODE_WORD_REPEATED); } // [Word repeated]\n        // Check for invalid negative values for words F, N, P, T, and S.\n        // NOTE: Negative value check is done here simply for code-efficiency.\n        if ( bit(word_bit) & (bit(WORD_F)|bit(WORD_N)|bit(WORD_P)|bit(WORD_T)|bit(WORD_S)) ) {\n          if (value < 0.0) { FAIL(STATUS_NEGATIVE_VALUE); } // [Word value cannot be negative]\n        }\n        value_words |= bit(word_bit); // Flag to indicate parameter assigned.\n      \n    }   \n  } \n  // Parsing complete!\n  \n\n  /* -------------------------------------------------------------------------------------\n     STEP 3: Error-check all commands and values passed in this block. This step ensures all of\n     the commands are valid for execution and follows the NIST standard as closely as possible.\n     If an error is found, all commands and values in this block are dumped and will not update\n     the active system g-code modes. If the block is ok, the active system g-code modes will be\n     updated based on the commands of this block, and signal for it to be executed. \n     \n     Also, we have to pre-convert all of the values passed based on the modes set by the parsed\n     block. There are a number of error-checks that require target information that can only be\n     accurately calculated if we convert these values in conjunction with the error-checking.\n     This relegates the next execution step as only updating the system g-code modes and \n     performing the programmed actions in order. The execution step should not require any \n     conversion calculations and would only require minimal checks necessary to execute.\n  */\n\n  /* NOTE: At this point, the g-code block has been parsed and the block line can be freed.\n     NOTE: It's also possible, at some future point, to break up STEP 2, to allow piece-wise \n     parsing of the block on a per-word basis, rather than the entire block. This could remove \n     the need for maintaining a large string variable for the entire block and free up some memory. \n     To do this, this would simply need to retain all of the data in STEP 1, such as the new block\n     data struct, the modal group and value bitflag tracking variables, and axis array indices \n     compatible variables. This data contains all of the information necessary to error-check the \n     new g-code block when the EOL character is received. However, this would break Grbl's startup\n     lines in how it currently works and would require some refactoring to make it compatible.\n  */  \n  \n  // [0. Non-specific/common error-checks and miscellaneous setup]: \n  \n  // Determine implicit axis command conditions. Axis words have been passed, but no explicit axis\n  // command has been sent. If so, set axis command to current motion mode.\n  if (axis_words) {\n    if (!axis_command) { axis_command = AXIS_COMMAND_MOTION_MODE; } // Assign implicit motion-mode\n  }\n  \n  // Check for valid line number N value.\n  if (bit_istrue(value_words,bit(WORD_N))) {\n    // Line number value cannot be less than zero (done) or greater than max line number.\n    if (gc_block.values.n > MAX_LINE_NUMBER) { FAIL(STATUS_GCODE_INVALID_LINE_NUMBER); } // [Exceeds max line number]\n  }\n  // bit_false(value_words,bit(WORD_N)); // NOTE: Single-meaning value word. Set at end of error-checking.\n  \n  // Track for unused words at the end of error-checking.\n  // NOTE: Single-meaning value words are removed all at once at the end of error-checking, because\n  // they are always used when present. This was done to save a few bytes of flash. For clarity, the\n  // single-meaning value words may be removed as they are used. Also, axis words are treated in the\n  // same way. If there is an explicit/implicit axis command, XYZ words are always used and are \n  // are removed at the end of error-checking.  \n  \n  // [1. Comments ]: MSG's NOT SUPPORTED. Comment handling performed by protocol.\n  \n  // [2. Set feed rate mode ]: G93 F word missing with G1,G2/3 active, implicitly or explicitly. Feed rate\n  //   is not defined after switching to G94 from G93.\n  if (gc_block.modal.feed_rate == FEED_RATE_MODE_INVERSE_TIME) { // = G93\n    // NOTE: G38 can also operate in inverse time, but is undefined as an error. Missing F word check added here.\n    if (axis_command == AXIS_COMMAND_MOTION_MODE) { \n      if ((gc_block.modal.motion != MOTION_MODE_NONE) || (gc_block.modal.motion != MOTION_MODE_SEEK)) {\n        if (bit_isfalse(value_words,bit(WORD_F))) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); } // [F word missing]\n      }\n    }\n    // NOTE: It seems redundant to check for an F word to be passed after switching from G94 to G93. We would\n    // accomplish the exact same thing if the feed rate value is always reset to zero and undefined after each\n    // inverse time block, since the commands that use this value already perform undefined checks. This would\n    // also allow other commands, following this switch, to execute and not error out needlessly. This code is \n    // combined with the above feed rate mode and the below set feed rate error-checking.\n\n    // [3. Set feed rate ]: F is negative (done.)\n    // - In inverse time mode: Always implicitly zero the feed rate value before and after block completion.\n    // NOTE: If in G93 mode or switched into it from G94, just keep F value as initialized zero or passed F word \n    // value in the block. If no F word is passed with a motion command that requires a feed rate, this will error \n    // out in the motion modes error-checking. However, if no F word is passed with NO motion command that requires\n    // a feed rate, we simply move on and the state feed rate value gets updated to zero and remains undefined.\n  } else { // = G94\n    // - In units per mm mode: If F word passed, ensure value is in mm/min, otherwise push last state value.\n    if (gc_state.modal.feed_rate == FEED_RATE_MODE_UNITS_PER_MIN) { // Last state is also G94\n      if (bit_istrue(value_words,bit(WORD_F))) {\n        if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.f *= MM_PER_INCH; }\n      } else {\n        gc_block.values.f = gc_state.feed_rate; // Push last state feed rate\n      }\n    } // Else, switching to G94 from G93, so don't push last state feed rate. Its undefined or the passed F word value.\n  } \n  // bit_false(value_words,bit(WORD_F)); // NOTE: Single-meaning value word. Set at end of error-checking.\n  \n  // [4. Set spindle speed ]: S is negative (done.)\n  if (bit_isfalse(value_words,bit(WORD_S))) { gc_block.values.s = gc_state.spindle_speed; }\n  // bit_false(value_words,bit(WORD_S)); // NOTE: Single-meaning value word. Set at end of error-checking.\n    \n  // [5. Select tool ]: NOT SUPPORTED. Only tracks value. T is negative (done.) Not an integer. Greater than max tool value.\n  // bit_false(value_words,bit(WORD_T)); // NOTE: Single-meaning value word. Set at end of error-checking.\n\n  // [6. Change tool ]: N/A\n  // [7. Spindle control ]: N/A\n  // [8. Coolant control ]: N/A\n  // [9. Enable/disable feed rate or spindle overrides ]: NOT SUPPORTED.\n  \n  // [10. Dwell ]: P value missing. P is negative (done.) NOTE: See below.\n  if (gc_block.non_modal_command == NON_MODAL_DWELL) {\n    if (bit_isfalse(value_words,bit(WORD_P))) { FAIL(STATUS_GCODE_VALUE_WORD_MISSING); } // [P word missing]\n    bit_false(value_words,bit(WORD_P));\n  }\n  \n  // [11. Set active plane ]: N/A\n  switch (gc_block.modal.plane_select) {\n    case PLANE_SELECT_XY:\n      axis_0 = X_AXIS;\n      axis_1 = Y_AXIS;\n      axis_linear = Z_AXIS;\n      break;\n    case PLANE_SELECT_ZX:\n      axis_0 = Z_AXIS;\n      axis_1 = X_AXIS;\n      axis_linear = Y_AXIS;\n      break;\n    default: // case PLANE_SELECT_YZ:\n      axis_0 = Y_AXIS;\n      axis_1 = Z_AXIS;\n      axis_linear = X_AXIS;\n  }   \n            \n  // [12. Set length units ]: N/A\n  // Pre-convert XYZ coordinate values to millimeters, if applicable.\n  uint8_t idx;\n  if (gc_block.modal.units == UNITS_MODE_INCHES) {\n    for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used.\n      if (bit_istrue(axis_words,bit(idx)) ) {\n        gc_block.values.xyz[idx] *= MM_PER_INCH;\n      }\n    }\n  }\n  \n  // [13. Cutter radius compensation ]: G41/42 NOT SUPPORTED. Error, if enabled while G53 is active.\n  // [G40 Errors]: G2/3 arc is programmed after a G40. The linear move after disabling is less than tool diameter.\n  //   NOTE: Since cutter radius compensation is never enabled, these G40 errors don't apply. Grbl supports G40 \n  //   only for the purpose to not error when G40 is sent with a g-code program header to setup the default modes.\n  \n  // [14. Cutter length compensation ]: G43 NOT SUPPORTED, but G43.1 and G49 are. \n  // [G43.1 Errors]: Motion command in same line. \n  //   NOTE: Although not explicitly stated so, G43.1 should be applied to only one valid \n  //   axis that is configured (in config.h). There should be an error if the configured axis\n  //   is absent or if any of the other axis words are present.\n  if (axis_command == AXIS_COMMAND_TOOL_LENGTH_OFFSET ) { // Indicates called in block.\n    if (gc_block.modal.tool_length == TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC) {\n      if (axis_words ^ (1<<TOOL_LENGTH_OFFSET_AXIS)) { FAIL(STATUS_GCODE_G43_DYNAMIC_AXIS_ERROR); }\n    }\n  }\n  \n  // [15. Coordinate system selection ]: *N/A. Error, if cutter radius comp is active.\n  // TODO: An EEPROM read of the coordinate data may require a buffer sync when the cycle\n  // is active. The read pauses the processor temporarily and may cause a rare crash. For \n  // future versions on processors with enough memory, all coordinate data should be stored\n  // in memory and written to EEPROM only when there is not a cycle active.\n  memcpy(coordinate_data,gc_state.coord_system,sizeof(gc_state.coord_system));\n  if ( bit_istrue(command_words,bit(MODAL_GROUP_G12)) ) { // Check if called in block\n    if (gc_block.modal.coord_select > N_COORDINATE_SYSTEM) { FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); } // [Greater than N sys]\n    if (gc_state.modal.coord_select != gc_block.modal.coord_select) {\n      if (!(settings_read_coord_data(gc_block.modal.coord_select,coordinate_data))) { FAIL(STATUS_SETTING_READ_FAIL); } \n    }\n  }\n  \n  // [16. Set path control mode ]: N/A. Only G61. G61.1 and G64 NOT SUPPORTED.\n  // [17. Set distance mode ]: N/A. Only G91.1. G90.1 NOT SUPPORTED.\n  // [18. Set retract mode ]: NOT SUPPORTED.\n  \n  // [19. Remaining non-modal actions ]: Check go to predefined position, set G10, or set axis offsets.\n  // NOTE: We need to separate the non-modal commands that are axis word-using (G10/G28/G30/G92), as these\n  // commands all treat axis words differently. G10 as absolute offsets or computes current position as\n  // the axis value, G92 similarly to G10 L20, and G28/30 as an intermediate target position that observes\n  // all the current coordinate system and G92 offsets. \n  switch (gc_block.non_modal_command) {\n    case NON_MODAL_SET_COORDINATE_DATA:  \n      // [G10 Errors]: L missing and is not 2 or 20. P word missing. (Negative P value done.)\n      // [G10 L2 Errors]: R word NOT SUPPORTED. P value not 0 to nCoordSys(max 9). Axis words missing.\n      // [G10 L20 Errors]: P must be 0 to nCoordSys(max 9). Axis words missing.\n      if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS) }; // [No axis words]\n      if (bit_isfalse(value_words,((1<<WORD_P)|(1<<WORD_L)))) { FAIL(STATUS_GCODE_VALUE_WORD_MISSING); } // [P/L word missing]\n      coord_select = trunc(gc_block.values.p); // Convert p value to int.\n      if (coord_select > N_COORDINATE_SYSTEM) { FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); } // [Greater than N sys]\n      if (gc_block.values.l != 20) {\n        if (gc_block.values.l == 2) {\n          if (bit_istrue(value_words,bit(WORD_R))) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G10 L2 R not supported]\n        } else { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [Unsupported L]\n      }\n      bit_false(value_words,(bit(WORD_L)|bit(WORD_P)));\n      \n      // Determine coordinate system to change and try to load from EEPROM.\n      if (coord_select > 0) { coord_select--; } // Adjust P1-P6 index to EEPROM coordinate data indexing.\n      else { coord_select = gc_block.modal.coord_select; } // Index P0 as the active coordinate system\n      if (!settings_read_coord_data(coord_select,parameter_data)) { FAIL(STATUS_SETTING_READ_FAIL); } // [EEPROM read fail]\n    \n      // Pre-calculate the coordinate data changes. NOTE: Uses parameter_data since coordinate_data may be in use by G54-59.\n      for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used.\n        // Update axes defined only in block. Always in machine coordinates. Can change non-active system.\n        if (bit_istrue(axis_words,bit(idx)) ) {\n          if (gc_block.values.l == 20) {\n            // L20: Update coordinate system axis at current position (with modifiers) with programmed value\n            parameter_data[idx] = gc_state.position[idx]-gc_state.coord_offset[idx]-gc_block.values.xyz[idx];\n            if (idx == TOOL_LENGTH_OFFSET_AXIS) { parameter_data[idx] -= gc_state.tool_length_offset; }\n          } else {\n            // L2: Update coordinate system axis to programmed value.\n            parameter_data[idx] = gc_block.values.xyz[idx]; \n          }\n        }\n      }\n      break;\n    case NON_MODAL_SET_COORDINATE_OFFSET:\n      // [G92 Errors]: No axis words.\n      if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]\n    \n      // Update axes defined only in block. Offsets current system to defined value. Does not update when\n      // active coordinate system is selected, but is still active unless G92.1 disables it. \n      for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used.\n        if (bit_istrue(axis_words,bit(idx)) ) {\n          gc_block.values.xyz[idx] = gc_state.position[idx]-coordinate_data[idx]-gc_block.values.xyz[idx];\n          if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.xyz[idx] -= gc_state.tool_length_offset; }\n        } else {\n          gc_block.values.xyz[idx] = gc_state.coord_offset[idx];\n        }\n      }\n      break;\n      \n    default:\n\n      // At this point, the rest of the explicit axis commands treat the axis values as the traditional\n      // target position with the coordinate system offsets, G92 offsets, absolute override, and distance\n      // modes applied. This includes the motion mode commands. We can now pre-compute the target position.\n      // NOTE: Tool offsets may be appended to these conversions when/if this feature is added.\n      if (axis_command != AXIS_COMMAND_TOOL_LENGTH_OFFSET ) { // TLO block any axis command.\n        if (axis_words) {\n          for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used to save flash space.\n            if ( bit_isfalse(axis_words,bit(idx)) ) {\n              gc_block.values.xyz[idx] = gc_state.position[idx]; // No axis word in block. Keep same axis position.\n            } else {\n              // Update specified value according to distance mode or ignore if absolute override is active.\n              // NOTE: G53 is never active with G28/30 since they are in the same modal group.\n              if (gc_block.non_modal_command != NON_MODAL_ABSOLUTE_OVERRIDE) {\n                // Apply coordinate offsets based on distance mode.\n                if (gc_block.modal.distance == DISTANCE_MODE_ABSOLUTE) {\n                  gc_block.values.xyz[idx] += coordinate_data[idx] + gc_state.coord_offset[idx];\n                  if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.xyz[idx] += gc_state.tool_length_offset; }\n                } else {  // Incremental mode\n                  gc_block.values.xyz[idx] += gc_state.position[idx];\n                }\n              }\n            }\n          }\n        }\n      }\n          \n      // Check remaining non-modal commands for errors.\n      switch (gc_block.non_modal_command) {        \n        case NON_MODAL_GO_HOME_0: \n          // [G28 Errors]: Cutter compensation is enabled. \n          // Retreive G28 go-home position data (in machine coordinates) from EEPROM\n          if (!axis_words) { axis_command = AXIS_COMMAND_NONE; } // Set to none if no intermediate motion.\n          if (!settings_read_coord_data(SETTING_INDEX_G28,parameter_data)) { FAIL(STATUS_SETTING_READ_FAIL); }\n          break;\n        case NON_MODAL_GO_HOME_1:\n          // [G30 Errors]: Cutter compensation is enabled. \n          // Retreive G30 go-home position data (in machine coordinates) from EEPROM\n          if (!axis_words) { axis_command = AXIS_COMMAND_NONE; } // Set to none if no intermediate motion.\n          if (!settings_read_coord_data(SETTING_INDEX_G30,parameter_data)) { FAIL(STATUS_SETTING_READ_FAIL); }\n          break;\n        case NON_MODAL_SET_HOME_0: case NON_MODAL_SET_HOME_1:\n          // [G28.1/30.1 Errors]: Cutter compensation is enabled. \n          // NOTE: If axis words are passed here, they are interpreted as an implicit motion mode.\n          break;\n        case NON_MODAL_RESET_COORDINATE_OFFSET: \n          // NOTE: If axis words are passed here, they are interpreted as an implicit motion mode.\n          break;\n        case NON_MODAL_ABSOLUTE_OVERRIDE:\n          // [G53 Errors]: G0 and G1 are not active. Cutter compensation is enabled.\n          // NOTE: All explicit axis word commands are in this modal group. So no implicit check necessary.\n          if (!(gc_block.modal.motion == MOTION_MODE_SEEK || gc_block.modal.motion == MOTION_MODE_LINEAR)) {\n            FAIL(STATUS_GCODE_G53_INVALID_MOTION_MODE); // [G53 G0/1 not active]\n          }\n          break;\n      }\n  }\n      \n  // [20. Motion modes ]: \n  if (gc_block.modal.motion == MOTION_MODE_NONE) {\n    // [G80 Errors]: Axis word exist and are not used by a non-modal command.\n    if ((axis_words) && (axis_command != AXIS_COMMAND_NON_MODAL)) { \n      FAIL(STATUS_GCODE_AXIS_WORDS_EXIST); // [No axis words allowed]\n    }\n\n  // Check remaining motion modes, if axis word are implicit (exist and not used by G10/28/30/92), or \n  // was explicitly commanded in the g-code block.\n  } else if ( axis_command == AXIS_COMMAND_MOTION_MODE ) {\n  \n    if (gc_block.modal.motion == MOTION_MODE_SEEK) {\n      // [G0 Errors]: Axis letter not configured or without real value (done.)\n      // Axis words are optional. If missing, set axis command flag to ignore execution.\n      if (!axis_words) { axis_command = AXIS_COMMAND_NONE; }\n\n    // All remaining motion modes (all but G0 and G80), require a valid feed rate value. In units per mm mode,\n    // the value must be positive. In inverse time mode, a positive value must be passed with each block.\n    } else {      \n      // Check if feed rate is defined for the motion modes that require it.\n      if (gc_block.values.f == 0.0) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); } // [Feed rate undefined]\n     \n      switch (gc_block.modal.motion) {\n        case MOTION_MODE_LINEAR: \n          // [G1 Errors]: Feed rate undefined. Axis letter not configured or without real value.\n          // Axis words are optional. If missing, set axis command flag to ignore execution.\n          if (!axis_words) { axis_command = AXIS_COMMAND_NONE; }\n\n          break;\n        case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC:\n          // [G2/3 Errors All-Modes]: Feed rate undefined.\n          // [G2/3 Radius-Mode Errors]: No axis words in selected plane. Target point is same as current.\n          // [G2/3 Offset-Mode Errors]: No axis words and/or offsets in selected plane. The radius to the current \n          //   point and the radius to the target point differs more than 0.002mm (EMC def. 0.5mm OR 0.005mm and 0.1% radius).   \n          // [G2/3 Full-Circle-Mode Errors]: NOT SUPPORTED. Axis words exist. No offsets programmed. P must be an integer.        \n          // NOTE: Both radius and offsets are required for arc tracing and are pre-computed with the error-checking.\n        \n          if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]\n          if (!(axis_words & (bit(axis_0)|bit(axis_1)))) { FAIL(STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE); } // [No axis words in plane]\n        \n          // Calculate the change in position along each selected axis\n          float x,y;\n          x = gc_block.values.xyz[axis_0]-gc_state.position[axis_0]; // Delta x between current position and target\n          y = gc_block.values.xyz[axis_1]-gc_state.position[axis_1]; // Delta y between current position and target\n\n          if (value_words & bit(WORD_R)) { // Arc Radius Mode  \n            bit_false(value_words,bit(WORD_R));\n            if (gc_check_same_position(gc_state.position, gc_block.values.xyz)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Invalid target]\n          \n            // Convert radius value to proper units.\n            if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.r *= MM_PER_INCH; }\n            /*  We need to calculate the center of the circle that has the designated radius and passes\n                through both the current position and the target position. This method calculates the following\n                set of equations where [x,y] is the vector from current to target position, d == magnitude of \n                that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to\n                the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the \n                length of h [-y/d*h, x/d*h] and added to the center of the travel vector [x/2,y/2] to form the new point \n                [i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc.\n    \n                d^2 == x^2 + y^2\n                h^2 == r^2 - (d/2)^2\n                i == x/2 - y/d*h\n                j == y/2 + x/d*h\n    \n                                                                     O <- [i,j]\n                                                                  -  |\n                                                        r      -     |\n                                                            -        |\n                                                         -           | h\n                                                      -              |\n                                        [0,0] ->  C -----------------+--------------- T  <- [x,y]\n                                                  | <------ d/2 ---->|\n              \n                C - Current position\n                T - Target position\n                O - center of circle that pass through both C and T\n                d - distance from C to T\n                r - designated radius\n                h - distance from center of CT to O\n    \n                Expanding the equations:\n \n                d -> sqrt(x^2 + y^2)\n                h -> sqrt(4 * r^2 - x^2 - y^2)/2\n                i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 \n                j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2\n   \n                Which can be written:\n    \n                i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2\n                j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2\n    \n                Which we for size and speed reasons optimize to:\n \n                h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2)\n                i = (x - (y * h_x2_div_d))/2\n                j = (y + (x * h_x2_div_d))/2       \n            */      \n\n            // First, use h_x2_div_d to compute 4*h^2 to check if it is negative or r is smaller\n            // than d. If so, the sqrt of a negative number is complex and error out.\n            float h_x2_div_d = 4.0 * gc_block.values.r*gc_block.values.r - x*x - y*y;\n\n            if (h_x2_div_d < 0) { FAIL(STATUS_GCODE_ARC_RADIUS_ERROR); } // [Arc radius error]\n    \n            // Finish computing h_x2_div_d.\n            h_x2_div_d = -sqrt(h_x2_div_d)/hypot_f(x,y); // == -(h * 2 / d)\n            // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below)\n            if (gc_block.modal.motion == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; }  \n\n            /* The counter clockwise circle lies to the left of the target direction. When offset is positive,\n               the left hand circle will be generated - when it is negative the right hand circle is generated.\n          \n                                                                   T  <-- Target position\n                                                   \n                                                                   ^ \n                        Clockwise circles with this center         |          Clockwise circles with this center will have\n                        will have > 180 deg of angular travel      |          < 180 deg of angular travel, which is a good thing!\n                                                         \\         |          /   \n            center of arc when h_x2_div_d is positive ->  x <----- | -----> x <- center of arc when h_x2_div_d is negative\n                                                                   |\n                                                                   |\n                                                   \n                                                                   C  <-- Current position                                \n            */  \n            // Negative R is g-code-alese for \"I want a circle with more than 180 degrees of travel\" (go figure!), \n            // even though it is advised against ever generating such circles in a single line of g-code. By \n            // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of\n            // travel and thus we get the unadvisably long arcs as prescribed.\n            if (gc_block.values.r < 0) { \n                h_x2_div_d = -h_x2_div_d; \n                gc_block.values.r = -gc_block.values.r; // Finished with r. Set to positive for mc_arc\n            }        \n            // Complete the operation by calculating the actual center of the arc\n            gc_block.values.ijk[axis_0] = 0.5*(x-(y*h_x2_div_d));\n            gc_block.values.ijk[axis_1] = 0.5*(y+(x*h_x2_div_d));\n          \n          } else { // Arc Center Format Offset Mode  \n            if (!(ijk_words & (bit(axis_0)|bit(axis_1)))) { FAIL(STATUS_GCODE_NO_OFFSETS_IN_PLANE); } // [No offsets in plane]\n            bit_false(value_words,(bit(WORD_I)|bit(WORD_J)|bit(WORD_K)));  \n          \n            // Convert IJK values to proper units.\n            if (gc_block.modal.units == UNITS_MODE_INCHES) {\n              for (idx=0; idx<N_AXIS; idx++) { // Axes indices are consistent, so loop may be used to save flash space.\n                if (ijk_words & bit(idx)) { gc_block.values.ijk[idx] *= MM_PER_INCH; }\n              }\n            }         \n\n            // Arc radius from center to target\n            x -= gc_block.values.ijk[axis_0]; // Delta x between circle center and target\n            y -= gc_block.values.ijk[axis_1]; // Delta y between circle center and target\n            float target_r = hypot_f(x,y); \n\n            // Compute arc radius for mc_arc. Defined from current location to center.\n            gc_block.values.r = hypot_f(gc_block.values.ijk[axis_0], gc_block.values.ijk[axis_1]); \n            \n            // Compute difference between current location and target radii for final error-checks.\n            float delta_r = fabs(target_r-gc_block.values.r);\n            if (delta_r > 0.005) { \n              if (delta_r > 0.5) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Arc definition error] > 0.5mm\n              if (delta_r > (0.001*gc_block.values.r)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Arc definition error] > 0.005mm AND 0.1% radius\n            }\n          }\n          break;\n        case MOTION_MODE_PROBE_TOWARD: case MOTION_MODE_PROBE_TOWARD_NO_ERROR:\n        case MOTION_MODE_PROBE_AWAY: case MOTION_MODE_PROBE_AWAY_NO_ERROR:\n          // [G38 Errors]: Target is same current. No axis words. Cutter compensation is enabled. Feed rate\n          //   is undefined. Probe is triggered. NOTE: Probe check moved to probe cycle. Instead of returning\n          //   an error, it issues an alarm to prevent further motion to the probe. It's also done there to \n          //   allow the planner buffer to empty and move off the probe trigger before another probing cycle.\n          if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]\n          if (gc_check_same_position(gc_state.position, gc_block.values.xyz)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Invalid target]\n          break;\n      } \n    }\n  }\n  \n  // [21. Program flow ]: No error checks required.\n\n  // [0. Non-specific error-checks]: Complete unused value words check, i.e. IJK used when in arc\n  // radius mode, or axis words that aren't used in the block.  \n  bit_false(value_words,(bit(WORD_N)|bit(WORD_F)|bit(WORD_S)|bit(WORD_T))); // Remove single-meaning value words. \n  if (axis_command) { bit_false(value_words,(bit(WORD_X)|bit(WORD_Y)|bit(WORD_Z))); } // Remove axis words. \n  if (value_words) { FAIL(STATUS_GCODE_UNUSED_WORDS); } // [Unused words]\n\n   \n  /* -------------------------------------------------------------------------------------\n     STEP 4: EXECUTE!!\n     Assumes that all error-checking has been completed and no failure modes exist. We just\n     need to update the state and execute the block according to the order-of-execution.\n  */ \n  \n  // [0. Non-specific/common error-checks and miscellaneous setup]: \n  gc_state.line_number = gc_block.values.n;\n  \n  // [1. Comments feedback ]:  NOT SUPPORTED\n  \n  // [2. Set feed rate mode ]:\n  gc_state.modal.feed_rate = gc_block.modal.feed_rate;\n  \n  // [3. Set feed rate ]:\n  gc_state.feed_rate = gc_block.values.f; // Always copy this value. See feed rate error-checking.\n\n  // [4. Set spindle speed ]:\n  if (gc_state.spindle_speed != gc_block.values.s) { \n    // Update running spindle only if not in check mode and not already enabled.\n    if (gc_state.modal.spindle != SPINDLE_DISABLE) { spindle_run(gc_state.modal.spindle, gc_block.values.s); }\n    gc_state.spindle_speed = gc_block.values.s; \n  }\n    \n  // [5. Select tool ]: NOT SUPPORTED. Only tracks tool value.\n  gc_state.tool = gc_block.values.t;\n\n  // [6. Change tool ]: NOT SUPPORTED\n\n  // [7. Spindle control ]:\n  if (gc_state.modal.spindle != gc_block.modal.spindle) {\n    // Update spindle control and apply spindle speed when enabling it in this block.    \n    spindle_run(gc_block.modal.spindle, gc_state.spindle_speed);\n    gc_state.modal.spindle = gc_block.modal.spindle;    \n  }\n\n  // [8. Coolant control ]:  \n  if (gc_state.modal.coolant != gc_block.modal.coolant) {\n    coolant_run(gc_block.modal.coolant);\n    gc_state.modal.coolant = gc_block.modal.coolant;\n  }\n  \n  // [9. Enable/disable feed rate or spindle overrides ]: NOT SUPPORTED\n\n  // [10. Dwell ]:\n  if (gc_block.non_modal_command == NON_MODAL_DWELL) { mc_dwell(gc_block.values.p); }\n  \n  // [11. Set active plane ]:\n  gc_state.modal.plane_select = gc_block.modal.plane_select;  \n\n  // [12. Set length units ]:\n  gc_state.modal.units = gc_block.modal.units;\n\n  // [13. Cutter radius compensation ]: G41/42 NOT SUPPORTED\n  // gc_state.modal.cutter_comp = gc_block.modal.cutter_comp; // NOTE: Not needed since always disabled.\n\n  // [14. Cutter length compensation ]: G43.1 and G49 supported. G43 NOT SUPPORTED.\n  // NOTE: If G43 were supported, its operation wouldn't be any different from G43.1 in terms\n  // of execution. The error-checking step would simply load the offset value into the correct\n  // axis of the block XYZ value array. \n  if (axis_command == AXIS_COMMAND_TOOL_LENGTH_OFFSET ) { // Indicates a change.\n    gc_state.modal.tool_length = gc_block.modal.tool_length;\n    if (gc_state.modal.tool_length == TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC) { // G43.1\n      gc_state.tool_length_offset = gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS];\n    } else { // G49\n      gc_state.tool_length_offset = 0.0;\n    }\n  }\n  \n  // [15. Coordinate system selection ]:\n  if (gc_state.modal.coord_select != gc_block.modal.coord_select) {\n    gc_state.modal.coord_select = gc_block.modal.coord_select;\n    memcpy(gc_state.coord_system,coordinate_data,sizeof(coordinate_data));\n  }\n  \n  // [16. Set path control mode ]: G61.1/G64 NOT SUPPORTED\n  // gc_state.modal.control = gc_block.modal.control; // NOTE: Always default.\n  \n  // [17. Set distance mode ]:\n  gc_state.modal.distance = gc_block.modal.distance;\n  \n  // [18. Set retract mode ]: NOT SUPPORTED\n    \n  // [19. Go to predefined position, Set G10, or Set axis offsets ]:\n  switch(gc_block.non_modal_command) {\n    case NON_MODAL_SET_COORDINATE_DATA:    \n      settings_write_coord_data(coord_select,parameter_data);\n      // Update system coordinate system if currently active.\n      if (gc_state.modal.coord_select == coord_select) { memcpy(gc_state.coord_system,parameter_data,sizeof(parameter_data)); }\n      break;\n    case NON_MODAL_GO_HOME_0: case NON_MODAL_GO_HOME_1: \n      // Move to intermediate position before going home. Obeys current coordinate system and offsets \n      // and absolute and incremental modes.\n      if (axis_command) {\n        #ifdef USE_LINE_NUMBERS\n          mc_line(gc_block.values.xyz, -1.0, false, gc_state.line_number);\n        #else\n          mc_line(gc_block.values.xyz, -1.0, false);\n        #endif\n      }\n      #ifdef USE_LINE_NUMBERS\n        mc_line(parameter_data, -1.0, false, gc_state.line_number); \n      #else\n        mc_line(parameter_data, -1.0, false); \n      #endif\n      memcpy(gc_state.position, parameter_data, sizeof(parameter_data));\n      break;\n    case NON_MODAL_SET_HOME_0: \n      settings_write_coord_data(SETTING_INDEX_G28,gc_state.position);\n      break;\n    case NON_MODAL_SET_HOME_1:\n      settings_write_coord_data(SETTING_INDEX_G30,gc_state.position);\n      break;\n    case NON_MODAL_SET_COORDINATE_OFFSET:\n      memcpy(gc_state.coord_offset,gc_block.values.xyz,sizeof(gc_block.values.xyz));\n      break;\n    case NON_MODAL_RESET_COORDINATE_OFFSET: \n      clear_vector(gc_state.coord_offset); // Disable G92 offsets by zeroing offset vector.\n      break;\n  }\n\n  \n  // [20. Motion modes ]:\n  // NOTE: Commands G10,G28,G30,G92 lock out and prevent axis words from use in motion modes. \n  // Enter motion modes only if there are axis words or a motion mode command word in the block.\n  gc_state.modal.motion = gc_block.modal.motion;\n  if (gc_state.modal.motion != MOTION_MODE_NONE) {\n    if (axis_command == AXIS_COMMAND_MOTION_MODE) {\n      switch (gc_state.modal.motion) {\n        case MOTION_MODE_SEEK:\n          #ifdef USE_LINE_NUMBERS\n            mc_line(gc_block.values.xyz, -1.0, false, gc_state.line_number);\n          #else\n            mc_line(gc_block.values.xyz, -1.0, false);\n          #endif\n          break;\n        case MOTION_MODE_LINEAR:\n          #ifdef USE_LINE_NUMBERS\n            mc_line(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, gc_state.line_number);\n          #else\n            mc_line(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate);\n          #endif\n          break;\n        case MOTION_MODE_CW_ARC: \n          #ifdef USE_LINE_NUMBERS\n            mc_arc(gc_state.position, gc_block.values.xyz, gc_block.values.ijk, gc_block.values.r, \n              gc_state.feed_rate, gc_state.modal.feed_rate, axis_0, axis_1, axis_linear, true, gc_state.line_number);  \n          #else\n            mc_arc(gc_state.position, gc_block.values.xyz, gc_block.values.ijk, gc_block.values.r, \n              gc_state.feed_rate, gc_state.modal.feed_rate, axis_0, axis_1, axis_linear, true); \n          #endif\n          break;        \n        case MOTION_MODE_CCW_ARC:\n          #ifdef USE_LINE_NUMBERS\n            mc_arc(gc_state.position, gc_block.values.xyz, gc_block.values.ijk, gc_block.values.r, \n              gc_state.feed_rate, gc_state.modal.feed_rate, axis_0, axis_1, axis_linear, false, gc_state.line_number);  \n          #else\n            mc_arc(gc_state.position, gc_block.values.xyz, gc_block.values.ijk, gc_block.values.r, \n              gc_state.feed_rate, gc_state.modal.feed_rate, axis_0, axis_1, axis_linear, false); \n          #endif\n          break;\n        case MOTION_MODE_PROBE_TOWARD: \n          // NOTE: gc_block.values.xyz is returned from mc_probe_cycle with the updated position value. So\n          // upon a successful probing cycle, the machine position and the returned value should be the same.\n          #ifdef USE_LINE_NUMBERS\n            mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, false, false, gc_state.line_number);\n          #else\n            mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, false, false);\n          #endif\n          break;\n        case MOTION_MODE_PROBE_TOWARD_NO_ERROR:\n          #ifdef USE_LINE_NUMBERS\n            mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, false, true, gc_state.line_number);\n          #else\n            mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, false, true);\n          #endif\n          break;\n        case MOTION_MODE_PROBE_AWAY:\n          #ifdef USE_LINE_NUMBERS\n            mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, true, false, gc_state.line_number);\n          #else\n            mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, true, false);\n          #endif\n          break;\n        case MOTION_MODE_PROBE_AWAY_NO_ERROR:\n          #ifdef USE_LINE_NUMBERS\n            mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, true, true, gc_state.line_number);\n          #else        \n            mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, true, true);\n          #endif\n      }\n    \n      // As far as the parser is concerned, the position is now == target. In reality the\n      // motion control system might still be processing the action and the real tool position\n      // in any intermediate location.\n      memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc_state.position[] = gc_block.values.xyz[]\n    }\n  }\n  \n  // [21. Program flow ]:\n  // M0,M1,M2,M30: Perform non-running program flow actions. During a program pause, the buffer may \n  // refill and can only be resumed by the cycle start run-time command.\n  gc_state.modal.program_flow = gc_block.modal.program_flow;\n  if (gc_state.modal.program_flow) { \n\tprotocol_buffer_synchronize(); // Sync and finish all remaining buffered motions before moving on.\n\tif (gc_state.modal.program_flow == PROGRAM_FLOW_PAUSED) {\n\t  if (sys.state != STATE_CHECK_MODE) {\n\t\tbit_true_atomic(sys.rt_exec_state, EXEC_FEED_HOLD); // Use feed hold for program pause.\n\t\tprotocol_execute_realtime(); // Execute suspend.\n\t  }\n\t} else { // == PROGRAM_FLOW_COMPLETED\n\t  // Upon program complete, only a subset of g-codes reset to certain defaults, according to \n\t  // LinuxCNC's program end descriptions and testing. Only modal groups [G-code 1,2,3,5,7,12]\n\t  // and [M-code 7,8,9] reset to [G1,G17,G90,G94,G40,G54,M5,M9,M48]. The remaining modal groups\n\t  // [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.\n\t  gc_state.modal.motion = MOTION_MODE_LINEAR;\n\t  gc_state.modal.plane_select = PLANE_SELECT_XY;\n\t  gc_state.modal.distance = DISTANCE_MODE_ABSOLUTE;\n\t  gc_state.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN;\n\t  // gc_state.modal.cutter_comp = CUTTER_COMP_DISABLE; // Not supported.\n\t  gc_state.modal.coord_select = 0; // G54\n\t  gc_state.modal.spindle = SPINDLE_DISABLE;\n\t  gc_state.modal.coolant = COOLANT_DISABLE;\n\t  // gc_state.modal.override = OVERRIDE_DISABLE; // Not supported.\n\t  \n\t  // Execute coordinate change and spindle/coolant stop.\n\t  if (sys.state != STATE_CHECK_MODE) {\n\t\tif (!(settings_read_coord_data(gc_state.modal.coord_select,coordinate_data))) { FAIL(STATUS_SETTING_READ_FAIL); } \n\t\tmemcpy(gc_state.coord_system,coordinate_data,sizeof(coordinate_data));\n\t\tspindle_stop();\n\t\tcoolant_stop();\t\t\n\t  }\n\t  \n\t  report_feedback_message(MESSAGE_PROGRAM_END);\n\t}\n    gc_state.modal.program_flow = PROGRAM_FLOW_RUNNING; // Reset program flow.\n  }\n    \n  // TODO: % to denote start of program.\n  return(STATUS_OK);\n}\n        \n\n/* \n  Not supported:\n\n  - Canned cycles\n  - Tool radius compensation\n  - A,B,C-axes\n  - Evaluation of expressions\n  - Variables\n  - Override control (TBD)\n  - Tool changes\n  - Switches\n   \n   (*) Indicates optional parameter, enabled through config.h and re-compile\n   group 0 = {G92.2, G92.3} (Non modal: Cancel and re-enable G92 offsets)\n   group 1 = {G81 - G89} (Motion modes: Canned cycles)\n   group 4 = {M1} (Optional stop, ignored)\n   group 6 = {M6} (Tool change)\n   group 7 = {G41, G42} cutter radius compensation (G40 is supported)\n   group 8 = {G43} tool length offset (G43.1/G49 are supported)\n   group 8 = {*M7} enable mist coolant (* Compile-option)\n   group 9 = {M48, M49} enable/disable feed and speed override switches\n   group 10 = {G98, G99} return mode canned cycles\n   group 13 = {G61.1, G64} path control mode (G61 is supported)\n*/\n"
  },
  {
    "path": "gcode.h",
    "content": "/*\n  gcode.h - rs274/ngc parser.\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n  \n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef gcode_h\n#define gcode_h\n\n\n// Define modal group internal numbers for checking multiple command violations and tracking the \n// type of command that is called in the block. A modal group is a group of g-code commands that are\n// mutually exclusive, or cannot exist on the same line, because they each toggle a state or execute\n// a unique motion. These are defined in the NIST RS274-NGC v3 g-code standard, available online, \n// and are similar/identical to other g-code interpreters by manufacturers (Haas,Fanuc,Mazak,etc).\n// NOTE: Modal group define values must be sequential and starting from zero.\n#define MODAL_GROUP_G0 0 // [G4,G10,G28,G28.1,G30,G30.1,G53,G92,G92.1] Non-modal\n#define MODAL_GROUP_G1 1 // [G0,G1,G2,G3,G38.2,G38.3,G38.4,G38.5,G80] Motion\n#define MODAL_GROUP_G2 2 // [G17,G18,G19] Plane selection\n#define MODAL_GROUP_G3 3 // [G90,G91] Distance mode\n#define MODAL_GROUP_G4 4 // [G91.1] Arc IJK distance mode\n#define MODAL_GROUP_G5 5 // [G93,G94] Feed rate mode\n#define MODAL_GROUP_G6 6 // [G20,G21] Units\n#define MODAL_GROUP_G7 7 // [G40] Cutter radius compensation mode. G41/42 NOT SUPPORTED.\n#define MODAL_GROUP_G8 8 // [G43.1,G49] Tool length offset\n#define MODAL_GROUP_G12 9 // [G54,G55,G56,G57,G58,G59] Coordinate system selection\n#define MODAL_GROUP_G13 10 // [G61] Control mode\n\n#define MODAL_GROUP_M4 11  // [M0,M1,M2,M30] Stopping\n#define MODAL_GROUP_M7 12 // [M3,M4,M5] Spindle turning\n#define MODAL_GROUP_M8 13 // [M7,M8,M9] Coolant control\n\n// #define OTHER_INPUT_F 14\n// #define OTHER_INPUT_S 15\n// #define OTHER_INPUT_T 16\n\n// Define command actions for within execution-type modal groups (motion, stopping, non-modal). Used\n// internally by the parser to know which command to execute.\n\n// Modal Group G0: Non-modal actions\n#define NON_MODAL_NO_ACTION 0 // (Default: Must be zero)\n#define NON_MODAL_DWELL 1 // G4\n#define NON_MODAL_SET_COORDINATE_DATA 2 // G10\n#define NON_MODAL_GO_HOME_0 3 // G28\n#define NON_MODAL_SET_HOME_0 4 // G28.1\n#define NON_MODAL_GO_HOME_1 5 // G30\n#define NON_MODAL_SET_HOME_1 6 // G30.1\n#define NON_MODAL_ABSOLUTE_OVERRIDE 7 // G53\n#define NON_MODAL_SET_COORDINATE_OFFSET 8 // G92\n#define NON_MODAL_RESET_COORDINATE_OFFSET 9 //G92.1\n\n// Modal Group G1: Motion modes\n#define MOTION_MODE_SEEK 0 // G0 (Default: Must be zero)\n#define MOTION_MODE_LINEAR 1 // G1\n#define MOTION_MODE_CW_ARC 2  // G2\n#define MOTION_MODE_CCW_ARC 3  // G3\n#define MOTION_MODE_PROBE_TOWARD 4 // G38.2 NOTE: G38.2, G38.3, G38.4, G38.5 must be sequential. See report_gcode_modes().\n#define MOTION_MODE_PROBE_TOWARD_NO_ERROR 5 // G38.3\n#define MOTION_MODE_PROBE_AWAY 6 // G38.4\n#define MOTION_MODE_PROBE_AWAY_NO_ERROR 7 // G38.5\n#define MOTION_MODE_NONE 8 // G80\n\n// Modal Group G2: Plane select\n#define PLANE_SELECT_XY 0 // G17 (Default: Must be zero)\n#define PLANE_SELECT_ZX 1 // G18\n#define PLANE_SELECT_YZ 2 // G19\n\n// Modal Group G3: Distance mode\n#define DISTANCE_MODE_ABSOLUTE 0 // G90 (Default: Must be zero)\n#define DISTANCE_MODE_INCREMENTAL 1 // G91\n\n// Modal Group G4: Arc IJK distance mode\n#define DISTANCE_ARC_MODE_INCREMENTAL 0 // G91.1 (Default: Must be zero)\n\n// Modal Group M4: Program flow\n#define PROGRAM_FLOW_RUNNING 0 // (Default: Must be zero)\n#define PROGRAM_FLOW_PAUSED 1 // M0, M1\n#define PROGRAM_FLOW_COMPLETED 2 // M2, M30\n\n// Modal Group G5: Feed rate mode\n#define FEED_RATE_MODE_UNITS_PER_MIN 0 // G94 (Default: Must be zero)\n#define FEED_RATE_MODE_INVERSE_TIME 1 // G93\n\n// Modal Group G6: Units mode\n#define UNITS_MODE_MM 0 // G21 (Default: Must be zero)\n#define UNITS_MODE_INCHES 1 // G20\n\n// Modal Group G7: Cutter radius compensation mode\n#define CUTTER_COMP_DISABLE 0 // G40 (Default: Must be zero)\n\n// Modal Group G13: Control mode\n#define CONTROL_MODE_EXACT_PATH 0 // G61 (Default: Must be zero)\n\n// Modal Group M7: Spindle control\n#define SPINDLE_DISABLE 0 // M5 (Default: Must be zero)\n#define SPINDLE_ENABLE_CW 1 // M3\n#define SPINDLE_ENABLE_CCW 2 // M4\n\n// Modal Group M8: Coolant control\n#define COOLANT_DISABLE 0 // M9 (Default: Must be zero)\n#define COOLANT_MIST_ENABLE 1 // M7\n#define COOLANT_FLOOD_ENABLE 2 // M8\n\n// Modal Group G8: Tool length offset\n#define TOOL_LENGTH_OFFSET_CANCEL 0 // G49 (Default: Must be zero)\n#define TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC 1 // G43.1\n\n// Modal Group G12: Active work coordinate system\n// N/A: Stores coordinate system value (54-59) to change to.\n\n\n// Define parameter word mapping.\n#define WORD_F  0\n#define WORD_I  1\n#define WORD_J  2\n#define WORD_K  3\n#define WORD_L  4\n#define WORD_N  5\n#define WORD_P  6\n#define WORD_R  7\n#define WORD_S  8\n#define WORD_T  9\n#define WORD_X  10\n#define WORD_Y  11\n#define WORD_Z  12\n\n\n// NOTE: When this struct is zeroed, the above defines set the defaults for the system.\ntypedef struct {\n  uint8_t motion;          // {G0,G1,G2,G3,G38.2,G80}\n  uint8_t feed_rate;       // {G93,G94}\n  uint8_t units;           // {G20,G21}\n  uint8_t distance;        // {G90,G91}\n  // uint8_t distance_arc; // {G91.1} NOTE: Don't track. Only default supported.\n  uint8_t plane_select;    // {G17,G18,G19}\n  // uint8_t cutter_comp;  // {G40} NOTE: Don't track. Only default supported.\n  uint8_t tool_length;     // {G43.1,G49}\n  uint8_t coord_select;    // {G54,G55,G56,G57,G58,G59}\n  // uint8_t control;      // {G61} NOTE: Don't track. Only default supported.\n  uint8_t program_flow;    // {M0,M1,M2,M30}\n  uint8_t coolant;         // {M7,M8,M9}\n  uint8_t spindle;         // {M3,M4,M5}\n} gc_modal_t;  \n\ntypedef struct {\n  float f;         // Feed\n  float ijk[3];    // I,J,K Axis arc offsets\n  uint8_t l;       // G10 or canned cycles parameters\n  int32_t n;       // Line number\n  float p;         // G10 or dwell parameters\n  // float q;      // G82 peck drilling\n  float r;         // Arc radius\n  float s;         // Spindle speed\n  uint8_t t;       // Tool selection\n  float xyz[3];    // X,Y,Z Translational axes\n} gc_values_t;\n\n\ntypedef struct {\n  gc_modal_t modal;\n  \n  float spindle_speed;          // RPM\n  float feed_rate;              // Millimeters/min\n  uint8_t tool;                 // Tracks tool number. NOT USED.\n  int32_t line_number;          // Last line number sent\n\n  float position[N_AXIS];       // Where the interpreter considers the tool to be at this point in the code\n\n  float coord_system[N_AXIS];   // Current work coordinate system (G54+). Stores offset from absolute machine\n                                // position in mm. Loaded from EEPROM when called.  \n  float coord_offset[N_AXIS];   // Retains the G92 coordinate offset (work coordinates) relative to\n                                // machine zero in mm. Non-persistent. Cleared upon reset and boot.    \n  float tool_length_offset;     // Tracks tool length offset value when enabled.\n} parser_state_t;\nextern parser_state_t gc_state;\n\ntypedef struct {\n//   uint16_t command_words;  // NOTE: If this bitflag variable fills, G and M words can be separated.\n//   uint16_t value_words;\n\n  uint8_t non_modal_command;\n  gc_modal_t modal;\n  gc_values_t values;\n\n} parser_block_t;\nextern parser_block_t gc_block;\n\n// Initialize the parser\nvoid gc_init();\n\n// Execute one block of rs275/ngc/g-code\nuint8_t gc_execute_line(char *line);\n\n// Set g-code parser position. Input in steps.\nvoid gc_sync_position(); \n\n#endif\n"
  },
  {
    "path": "grbl.h",
    "content": "/*\n  grbl.h - main Grbl include file\n  Part of Grbl\n\n  Copyright (c) 2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef grbl_h\n#define grbl_h\n\n// Grbl versioning system\n#define GRBL_VERSION \"0.9i\"\n#define GRBL_VERSION_BUILD \"20150620\"\n\n// Define standard libraries used by Grbl.\n#include <avr/io.h>\n#include <avr/pgmspace.h>\n#include <avr/interrupt.h>\n#include <avr/wdt.h>\n#include <util/delay.h>\n#include <math.h>\n#include <inttypes.h>    \n#include <string.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <stdbool.h>\n\n// Define the Grbl system include files. NOTE: Do not alter organization.\n#include \"config.h\"\n#include \"nuts_bolts.h\"\n#include \"settings.h\"\n#include \"system.h\"\n#include \"defaults.h\"\n#include \"cpu_map.h\"\n#include \"coolant_control.h\"\n#include \"eeprom.h\"\n#include \"gcode.h\"\n#include \"limits.h\"\n#include \"motion_control.h\"\n#include \"planner.h\"\n#include \"print.h\"\n#include \"probe.h\"\n#include \"protocol.h\"\n#include \"report.h\"\n#include \"serial.h\"\n#include \"spindle_control.h\"\n#include \"stepper.h\"\n\n#endif\n"
  },
  {
    "path": "limits.c",
    "content": "/*\n  limits.c - code pertaining to limit-switches and performing the homing cycle\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n  \n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n  \n#include \"grbl.h\"\n\n\n// Homing axis search distance multiplier. Computed by this value times the cycle travel.\n#ifndef HOMING_AXIS_SEARCH_SCALAR\n  #define HOMING_AXIS_SEARCH_SCALAR  1.5 // Must be > 1 to ensure limit switch will be engaged.\n#endif\n#ifndef HOMING_AXIS_LOCATE_SCALAR\n  #define HOMING_AXIS_LOCATE_SCALAR  5.0 // Must be > 1 to ensure limit switch is cleared.\n#endif\n\nvoid limits_init() \n{\n  LIMIT_DDR &= ~(LIMIT_MASK); // Set as input pins\n\n  #ifdef DISABLE_LIMIT_PIN_PULL_UP\n    LIMIT_PORT &= ~(LIMIT_MASK); // Normal low operation. Requires external pull-down.\n  #else\n    LIMIT_PORT |= (LIMIT_MASK);  // Enable internal pull-up resistors. Normal high operation.\n  #endif\n\n  if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) {\n    LIMIT_PCMSK |= LIMIT_MASK; // Enable specific pins of the Pin Change Interrupt\n    PCICR |= (1 << LIMIT_INT); // Enable Pin Change Interrupt\n  } else {\n    limits_disable(); \n  }\n  \n  #ifdef ENABLE_SOFTWARE_DEBOUNCE\n    MCUSR &= ~(1<<WDRF);\n    WDTCSR |= (1<<WDCE) | (1<<WDE);\n    WDTCSR = (1<<WDP0); // Set time-out at ~32msec.\n  #endif\n}\n\n\n// Disables hard limits.\nvoid limits_disable()\n{\n  LIMIT_PCMSK &= ~LIMIT_MASK;  // Disable specific pins of the Pin Change Interrupt\n  PCICR &= ~(1 << LIMIT_INT);  // Disable Pin Change Interrupt\n}\n\n\n// Returns limit state as a bit-wise uint8 variable. Each bit indicates an axis limit, where \n// triggered is 1 and not triggered is 0. Invert mask is applied. Axes are defined by their\n// number in bit position, i.e. Z_AXIS is (1<<2) or bit 2, and Y_AXIS is (1<<1) or bit 1.\nuint8_t limits_get_state()\n{\n  uint8_t limit_state = 0;\n  uint8_t pin = (LIMIT_PIN & LIMIT_MASK);\n  if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { pin ^= LIMIT_MASK; }\n  if (pin) {  \n\tuint8_t idx;\n\tfor (idx=0; idx<N_AXIS; idx++) {\n\t  if (pin & get_limit_pin_mask(idx)) { limit_state |= (1 << idx); }\n\t}\n  }\n  return(limit_state);\n}\n\n\n// This is the Limit Pin Change Interrupt, which handles the hard limit feature. A bouncing \n// limit switch can cause a lot of problems, like false readings and multiple interrupt calls.\n// If a switch is triggered at all, something bad has happened and treat it as such, regardless\n// if a limit switch is being disengaged. It's impossible to reliably tell the state of a \n// bouncing pin without a debouncing method. A simple software debouncing feature may be enabled \n// through the config.h file, where an extra timer delays the limit pin read by several milli-\n// seconds to help with, not fix, bouncing switches.\n// NOTE: Do not attach an e-stop to the limit pins, because this interrupt is disabled during\n// homing cycles and will not respond correctly. Upon user request or need, there may be a\n// special pinout for an e-stop, but it is generally recommended to just directly connect\n// your e-stop switch to the Arduino reset pin, since it is the most correct way to do this.\n#ifndef ENABLE_SOFTWARE_DEBOUNCE\n  ISR(LIMIT_INT_vect) // DEFAULT: Limit pin change interrupt process. \n  {\n    // Ignore limit switches if already in an alarm state or in-process of executing an alarm.\n    // When in the alarm state, Grbl should have been reset or will force a reset, so any pending \n    // moves in the planner and serial buffers are all cleared and newly sent blocks will be \n    // locked out until a homing cycle or a kill lock command. Allows the user to disable the hard\n    // limit setting if their limits are constantly triggering after a reset and move their axes.\n    if (sys.state != STATE_ALARM) { \n      if (!(sys.rt_exec_alarm)) {\n        #ifdef HARD_LIMIT_FORCE_STATE_CHECK\n          // Check limit pin state. \n          if (limits_get_state()) {\n            mc_reset(); // Initiate system kill.\n            bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event\n          }\n        #else\n          mc_reset(); // Initiate system kill.\n          bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event\n        #endif\n      }\n    }\n  }  \n#else // OPTIONAL: Software debounce limit pin routine.\n  // Upon limit pin change, enable watchdog timer to create a short delay. \n  ISR(LIMIT_INT_vect) { if (!(WDTCSR & (1<<WDIE))) { WDTCSR |= (1<<WDIE); } }\n  ISR(WDT_vect) // Watchdog timer ISR\n  {\n    WDTCSR &= ~(1<<WDIE); // Disable watchdog timer. \n    if (sys.state != STATE_ALARM) {  // Ignore if already in alarm state. \n      if (!(sys.rt_exec_alarm)) {\n        // Check limit pin state. \n        if (limits_get_state()) {\n          mc_reset(); // Initiate system kill.\n          bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event\n        }\n      }  \n    }\n  }\n#endif\n\n \n// Homes the specified cycle axes, sets the machine position, and performs a pull-off motion after\n// completing. Homing is a special motion case, which involves rapid uncontrolled stops to locate\n// the trigger point of the limit switches. The rapid stops are handled by a system level axis lock \n// mask, which prevents the stepper algorithm from executing step pulses. Homing motions typically \n// circumvent the processes for executing motions in normal operation.\n// NOTE: Only the abort realtime command can interrupt this process.\n// TODO: Move limit pin-specific calls to a general function for portability.\nvoid limits_go_home(uint8_t cycle_mask) \n{\n  if (sys.abort) { return; } // Block if system reset has been issued.\n\n  // Initialize\n  uint8_t n_cycle = (2*N_HOMING_LOCATE_CYCLE+1);\n  uint8_t step_pin[N_AXIS];\n  float target[N_AXIS];\n  float max_travel = 0.0;\n  uint8_t idx;\n  for (idx=0; idx<N_AXIS; idx++) {  \n    // Initialize step pin masks\n    step_pin[idx] = get_step_pin_mask(idx);\n    #ifdef COREXY    \n      if ((idx==A_MOTOR)||(idx==B_MOTOR)) { step_pin[idx] = (get_step_pin_mask(X_AXIS)|get_step_pin_mask(Y_AXIS)); } \n    #endif\n\n    if (bit_istrue(cycle_mask,bit(idx))) { \n      // Set target based on max_travel setting. Ensure homing switches engaged with search scalar.\n      // NOTE: settings.max_travel[] is stored as a negative value.\n      max_travel = max(max_travel,(-HOMING_AXIS_SEARCH_SCALAR)*settings.max_travel[idx]);\n    }\n  }\n\n  // Set search mode with approach at seek rate to quickly engage the specified cycle_mask limit switches.\n  bool approach = true;\n  float homing_rate = settings.homing_seek_rate;\n\n  uint8_t limit_state, axislock, n_active_axis;\n  do {\n\n    system_convert_array_steps_to_mpos(target,sys.position);\n\n    // Initialize and declare variables needed for homing routine.\n    axislock = 0;\n    n_active_axis = 0;\n    for (idx=0; idx<N_AXIS; idx++) {\n      // Set target location for active axes and setup computation for homing rate.\n      if (bit_istrue(cycle_mask,bit(idx))) {\n        n_active_axis++;\n        sys.position[idx] = 0;\n        // Set target direction based on cycle mask and homing cycle approach state.\n        // NOTE: This happens to compile smaller than any other implementation tried.\n        if (bit_istrue(settings.homing_dir_mask,bit(idx))) {\n          if (approach) { target[idx] = -max_travel; }\n          else { target[idx] = max_travel; }\n        } else { \n          if (approach) { target[idx] = max_travel; }\n          else { target[idx] = -max_travel; }\n        }        \n        // Apply axislock to the step port pins active in this cycle.\n        axislock |= step_pin[idx];\n      }\n\n    }\n    homing_rate *= sqrt(n_active_axis); // [sqrt(N_AXIS)] Adjust so individual axes all move at homing rate.\n    sys.homing_axis_lock = axislock;\n\n    plan_sync_position(); // Sync planner position to current machine position.\n    \n    // Perform homing cycle. Planner buffer should be empty, as required to initiate the homing cycle.\n    #ifdef USE_LINE_NUMBERS\n      plan_buffer_line(target, homing_rate, false, HOMING_CYCLE_LINE_NUMBER); // Bypass mc_line(). Directly plan homing motion.\n    #else\n      plan_buffer_line(target, homing_rate, false); // Bypass mc_line(). Directly plan homing motion.\n    #endif\n    \n    st_prep_buffer(); // Prep and fill segment buffer from newly planned block.\n    st_wake_up(); // Initiate motion\n\tdo {\n\t  if (approach) {\n\t\t// Check limit state. Lock out cycle axes when they change.\n\t\tlimit_state = limits_get_state();\n\t\tfor (idx=0; idx<N_AXIS; idx++) {\n\t\t  if (axislock & step_pin[idx]) {\n\t\t\tif (limit_state & (1 << idx)) { axislock &= ~(step_pin[idx]); }\n\t\t  }\n\t\t}\n\t\tsys.homing_axis_lock = axislock;\n\t  }\n\n\t  st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us.\n\n\t  // Exit routines: No time to run protocol_execute_realtime() in this loop.\n\t  if (sys.rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET | EXEC_CYCLE_STOP)) {\n\t    // Homing failure: Limit switches are still engaged after pull-off motion\n\t\tif ( (sys.rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET)) ||  // Safety door or reset issued\n\t\t     (!approach && (limits_get_state() & cycle_mask)) ||  // Limit switch still engaged after pull-off motion\n\t\t     ( approach && (sys.rt_exec_state & EXEC_CYCLE_STOP)) ) { // Limit switch not found during approach.\n     \t  mc_reset(); // Stop motors, if they are running.\n\t\t  protocol_execute_realtime();\n\t\t  return;\n\t\t} else {\n\t\t  // Pull-off motion complete. Disable CYCLE_STOP from executing.\n          bit_false_atomic(sys.rt_exec_state,EXEC_CYCLE_STOP);\n\t\t  break;\n\t\t} \n\t  }\n\n\t} while (STEP_MASK & axislock);\n\n    st_reset(); // Immediately force kill steppers and reset step segment buffer.\n    plan_reset(); // Reset planner buffer to zero planner current position and to clear previous motions.\n\n    delay_ms(settings.homing_debounce_delay); // Delay to allow transient dynamics to dissipate.\n\n    // Reverse direction and reset homing rate for locate cycle(s).\n    approach = !approach;\n\n    // After first cycle, homing enters locating phase. Shorten search to pull-off distance.\n    if (approach) { \n      max_travel = settings.homing_pulloff*HOMING_AXIS_LOCATE_SCALAR; \n      homing_rate = settings.homing_feed_rate;\n    } else {\n      max_travel = settings.homing_pulloff;    \n      homing_rate = settings.homing_seek_rate;\n    }\n    \n  } while (n_cycle-- > 0);\n      \n  // The active cycle axes should now be homed and machine limits have been located. By \n  // default, Grbl defines machine space as all negative, as do most CNCs. Since limit switches\n  // can be on either side of an axes, check and set axes machine zero appropriately. Also,\n  // set up pull-off maneuver from axes limit switches that have been homed. This provides\n  // some initial clearance off the switches and should also help prevent them from falsely\n  // triggering when hard limits are enabled or when more than one axes shares a limit pin.\n  #ifdef COREXY\n    int32_t off_axis_position = 0;\n  #endif\n  int32_t set_axis_position;\n  // Set machine positions for homed limit switches. Don't update non-homed axes.\n  for (idx=0; idx<N_AXIS; idx++) {\n    // NOTE: settings.max_travel[] is stored as a negative value.\n    if (cycle_mask & bit(idx)) {\n      #ifdef HOMING_FORCE_SET_ORIGIN\n        set_axis_position = 0;\n      #else \n        if ( bit_istrue(settings.homing_dir_mask,bit(idx)) ) {\n          set_axis_position = lround((settings.max_travel[idx]+settings.homing_pulloff)*settings.steps_per_mm[idx]);\n        } else {\n          set_axis_position = lround(-settings.homing_pulloff*settings.steps_per_mm[idx]);\n        }\n      #endif\n      \n      #ifdef COREXY\n        if (idx==X_AXIS) { \n          off_axis_position = (sys.position[B_MOTOR] - sys.position[A_MOTOR])/2;\n          sys.position[A_MOTOR] = set_axis_position - off_axis_position;\n          sys.position[B_MOTOR] = set_axis_position + off_axis_position;          \n        } else if (idx==Y_AXIS) {\n          off_axis_position = (sys.position[A_MOTOR] + sys.position[B_MOTOR])/2;\n          sys.position[A_MOTOR] = off_axis_position - set_axis_position;\n          sys.position[B_MOTOR] = off_axis_position + set_axis_position;\n        } else {\n          sys.position[idx] = set_axis_position;\n        }        \n      #else \n        sys.position[idx] = set_axis_position;\n      #endif\n\n    }\n  }\n  plan_sync_position(); // Sync planner position to homed machine position.\n    \n  // sys.state = STATE_HOMING; // Ensure system state set as homing before returning. \n}\n\n\n// Performs a soft limit check. Called from mc_line() only. Assumes the machine has been homed,\n// the workspace volume is in all negative space, and the system is in normal operation.\nvoid limits_soft_check(float *target)\n{\n  uint8_t idx;\n  uint8_t soft_limit_error = false;\n  for (idx=0; idx<N_AXIS; idx++) {\n   \n    #ifdef HOMING_FORCE_SET_ORIGIN\n      // When homing forced set origin is enabled, soft limits checks need to account for directionality.\n      // NOTE: max_travel is stored as negative\n      if (bit_istrue(settings.homing_dir_mask,bit(idx))) {\n        if (target[idx] < 0 || target[idx] > -settings.max_travel[idx]) { soft_limit_error = true; }\n      } else {\n        if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { soft_limit_error = true; }\n      }\n    #else  \n      // NOTE: max_travel is stored as negative\n      if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { soft_limit_error = true; }\n    #endif\n    \n    if (soft_limit_error) {\n      // Force feed hold if cycle is active. All buffered blocks are guaranteed to be within \n      // workspace volume so just come to a controlled stop so position is not lost. When complete\n      // enter alarm mode.\n      if (sys.state == STATE_CYCLE) {\n        bit_true_atomic(sys.rt_exec_state, EXEC_FEED_HOLD);\n        do {\n          protocol_execute_realtime();\n          if (sys.abort) { return; }\n        } while ( sys.state != STATE_IDLE );\n      }\n    \n      mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown.\n      bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_SOFT_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate soft limit critical event\n      protocol_execute_realtime(); // Execute to enter critical event loop and system abort\n      return;\n    }\n  }\n}\n"
  },
  {
    "path": "limits.h",
    "content": "/*\n  limits.h - code pertaining to limit-switches and performing the homing cycle\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon  \n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n  \n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef limits_h\n#define limits_h \n\n\n// Initialize the limits module\nvoid limits_init();\n\n// Disables hard limits.\nvoid limits_disable();\n\n// Returns limit state as a bit-wise uint8 variable.\nuint8_t limits_get_state();\n\n// Perform one portion of the homing cycle based on the input settings.\nvoid limits_go_home(uint8_t cycle_mask);\n\n// Check for soft limit violations\nvoid limits_soft_check(float *target);\n\n#endif"
  },
  {
    "path": "main.c",
    "content": "/*\n  main.c - An embedded CNC Controller with rs274/ngc (g-code) support\n  Part of Grbl\n  \n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n  \n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"grbl.h\"\n\n\n// Declare system global variable structure\nsystem_t sys; \n\n\nint main(void)\n{\n  // Initialize system upon power-up.\n  serial_init();   // Setup serial baud rate and interrupts\n  settings_init(); // Load Grbl settings from EEPROM\n  stepper_init();  // Configure stepper pins and interrupt timers\n  system_init();   // Configure pinout pins and pin-change interrupt\n  \n  memset(&sys, 0, sizeof(sys));  // Clear all system variables\n  sys.abort = true;   // Set abort to complete initialization\n  sei(); // Enable interrupts\n\n  // Check for power-up and set system alarm if homing is enabled to force homing cycle\n  // by setting Grbl's alarm state. Alarm locks out all g-code commands, including the\n  // startup scripts, but allows access to settings and internal commands. Only a homing\n  // cycle '$H' or kill alarm locks '$X' will disable the alarm.\n  // NOTE: The startup script will run after successful completion of the homing cycle, but\n  // not after disabling the alarm locks. Prevents motion startup blocks from crashing into\n  // things uncontrollably. Very bad.\n  #ifdef HOMING_INIT_LOCK\n    if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { sys.state = STATE_ALARM; }\n  #endif\n  \n  // Force Grbl into an ALARM state upon a power-cycle or hard reset.\n  #ifdef FORCE_INITIALIZATION_ALARM\n    sys.state = STATE_ALARM;\n  #endif\n  \n  // Grbl initialization loop upon power-up or a system abort. For the latter, all processes\n  // will return to this loop to be cleanly re-initialized.\n  for(;;) {\n\n    // TODO: Separate configure task that require interrupts to be disabled, especially upon\n    // a system abort and ensuring any active interrupts are cleanly reset.\n  \n    // Reset Grbl primary systems.\n    serial_reset_read_buffer(); // Clear serial read buffer\n    gc_init(); // Set g-code parser to default state\n    spindle_init();\n    coolant_init();\n    limits_init(); \n    probe_init();\n    plan_reset(); // Clear block buffer and planner variables\n    st_reset(); // Clear stepper subsystem variables.\n\n    // Sync cleared gcode and planner positions to current system position.\n    plan_sync_position();\n    gc_sync_position();\n\n    // Reset system variables.\n    sys.abort = false;\n    sys.rt_exec_state = 0;\n    sys.rt_exec_alarm = 0;\n    sys.suspend = false;\n          \n    // Start Grbl main loop. Processes program inputs and executes them.\n    protocol_main_loop();\n    \n  }\n  return 0;   /* Never reached */\n}\n"
  },
  {
    "path": "motion_control.c",
    "content": "/*\n  motion_control.c - high level interface for issuing motion commands\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n  Copyright (c) 2011 Simen Svale Skogsrud\n  \n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"grbl.h\"\n\n\n// Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second\n// unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in\n// (1 minute)/feed_rate time.\n// NOTE: This is the primary gateway to the grbl planner. All line motions, including arc line \n// segments, must pass through this routine before being passed to the planner. The seperation of\n// mc_line and plan_buffer_line is done primarily to place non-planner-type functions from being\n// in the planner and to let backlash compensation or canned cycle integration simple and direct.\n#ifdef USE_LINE_NUMBERS\n  void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate, int32_t line_number)\n#else\n  void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate)\n#endif\n{\n  // If enabled, check for soft limit violations. Placed here all line motions are picked up\n  // from everywhere in Grbl.\n  if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) { limits_soft_check(target); }    \n      \n  // If in check gcode mode, prevent motion by blocking planner. Soft limits still work.\n  if (sys.state == STATE_CHECK_MODE) { return; }\n    \n  // NOTE: Backlash compensation may be installed here. It will need direction info to track when\n  // to insert a backlash line motion(s) before the intended line motion and will require its own\n  // plan_check_full_buffer() and check for system abort loop. Also for position reporting \n  // backlash steps will need to be also tracked, which will need to be kept at a system level.\n  // There are likely some other things that will need to be tracked as well. However, we feel\n  // that backlash compensation should NOT be handled by Grbl itself, because there are a myriad\n  // of ways to implement it and can be effective or ineffective for different CNC machines. This\n  // would be better handled by the interface as a post-processor task, where the original g-code\n  // is translated and inserts backlash motions that best suits the machine. \n  // NOTE: Perhaps as a middle-ground, all that needs to be sent is a flag or special command that\n  // indicates to Grbl what is a backlash compensation motion, so that Grbl executes the move but\n  // doesn't update the machine position values. Since the position values used by the g-code\n  // parser and planner are separate from the system machine positions, this is doable.\n\n  // If the buffer is full: good! That means we are well ahead of the robot. \n  // Remain in this loop until there is room in the buffer.\n  do {\n    protocol_execute_realtime(); // Check for any run-time commands\n    if (sys.abort) { return; } // Bail, if system abort.\n    if ( plan_check_full_buffer() ) { protocol_auto_cycle_start(); } // Auto-cycle start when buffer is full.\n    else { break; }\n  } while (1);\n\n  // Plan and queue motion into planner buffer\n  #ifdef USE_LINE_NUMBERS\n    plan_buffer_line(target, feed_rate, invert_feed_rate, line_number);\n  #else\n    plan_buffer_line(target, feed_rate, invert_feed_rate);\n  #endif\n}\n\n\n// Execute an arc in offset mode format. position == current xyz, target == target xyz, \n// offset == offset from current xyz, axis_X defines circle plane in tool space, axis_linear is\n// the direction of helical travel, radius == circle radius, isclockwise boolean. Used\n// for vector transformation direction.\n// The arc is approximated by generating a huge number of tiny, linear segments. The chordal tolerance\n// of each segment is configured in settings.arc_tolerance, which is defined to be the maximum normal\n// distance from segment to the circle when the end points both lie on the circle.\n#ifdef USE_LINE_NUMBERS\n  void mc_arc(float *position, float *target, float *offset, float radius, float feed_rate, \n    uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc, int32_t line_number)\n#else\n  void mc_arc(float *position, float *target, float *offset, float radius, float feed_rate,\n    uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc)\n#endif\n{\n  float center_axis0 = position[axis_0] + offset[axis_0];\n  float center_axis1 = position[axis_1] + offset[axis_1];\n  float r_axis0 = -offset[axis_0];  // Radius vector from center to current location\n  float r_axis1 = -offset[axis_1];\n  float rt_axis0 = target[axis_0] - center_axis0;\n  float rt_axis1 = target[axis_1] - center_axis1;\n  \n  // CCW angle between position and target from circle center. Only one atan2() trig computation required.\n  float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);\n  if (is_clockwise_arc) { // Correct atan2 output per direction\n    if (angular_travel >= -ARC_ANGULAR_TRAVEL_EPSILON) { angular_travel -= 2*M_PI; }\n  } else {\n    if (angular_travel <= ARC_ANGULAR_TRAVEL_EPSILON) { angular_travel += 2*M_PI; }\n  }\n\n  // NOTE: Segment end points are on the arc, which can lead to the arc diameter being smaller by up to\n  // (2x) settings.arc_tolerance. For 99% of users, this is just fine. If a different arc segment fit\n  // is desired, i.e. least-squares, midpoint on arc, just change the mm_per_arc_segment calculation.\n  // For the intended uses of Grbl, this value shouldn't exceed 2000 for the strictest of cases.\n  uint16_t segments = floor(fabs(0.5*angular_travel*radius)/\n                          sqrt(settings.arc_tolerance*(2*radius - settings.arc_tolerance)) );\n  \n  if (segments) { \n    // Multiply inverse feed_rate to compensate for the fact that this movement is approximated\n    // by a number of discrete segments. The inverse feed_rate should be correct for the sum of \n    // all segments.\n    if (invert_feed_rate) { feed_rate *= segments; }\n   \n    float theta_per_segment = angular_travel/segments;\n    float linear_per_segment = (target[axis_linear] - position[axis_linear])/segments;\n\n    /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,\n       and phi is the angle of rotation. Solution approach by Jens Geisler.\n           r_T = [cos(phi) -sin(phi);\n                  sin(phi)  cos(phi] * r ;\n       \n       For arc generation, the center of the circle is the axis of rotation and the radius vector is \n       defined from the circle center to the initial position. Each line segment is formed by successive\n       vector rotations. Single precision values can accumulate error greater than tool precision in rare\n       cases. So, exact arc path correction is implemented. This approach avoids the problem of too many very\n       expensive trig operations [sin(),cos(),tan()] which can take 100-200 usec each to compute.\n  \n       Small angle approximation may be used to reduce computation overhead further. A third-order approximation\n       (second order sin() has too much error) holds for most, if not, all CNC applications. Note that this \n       approximation will begin to accumulate a numerical drift error when theta_per_segment is greater than \n       ~0.25 rad(14 deg) AND the approximation is successively used without correction several dozen times. This\n       scenario is extremely unlikely, since segment lengths and theta_per_segment are automatically generated\n       and scaled by the arc tolerance setting. Only a very large arc tolerance setting, unrealistic for CNC \n       applications, would cause this numerical drift error. However, it is best to set N_ARC_CORRECTION from a\n       low of ~4 to a high of ~20 or so to avoid trig operations while keeping arc generation accurate.\n       \n       This approximation also allows mc_arc to immediately insert a line segment into the planner \n       without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied\n       a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead. \n       This is important when there are successive arc motions. \n    */\n    // Computes: cos_T = 1 - theta_per_segment^2/2, sin_T = theta_per_segment - theta_per_segment^3/6) in ~52usec\n    float cos_T = 2.0 - theta_per_segment*theta_per_segment;\n    float sin_T = theta_per_segment*0.16666667*(cos_T + 4.0);\n    cos_T *= 0.5;\n\n    float sin_Ti;\n    float cos_Ti;\n    float r_axisi;\n    uint16_t i;\n    uint8_t count = 0;\n  \n    for (i = 1; i<segments; i++) { // Increment (segments-1).\n      \n      if (count < N_ARC_CORRECTION) {\n        // Apply vector rotation matrix. ~40 usec\n        r_axisi = r_axis0*sin_T + r_axis1*cos_T;\n        r_axis0 = r_axis0*cos_T - r_axis1*sin_T;\n        r_axis1 = r_axisi;\n        count++;\n      } else {      \n        // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments. ~375 usec\n        // Compute exact location by applying transformation matrix from initial radius vector(=-offset).\n        cos_Ti = cos(i*theta_per_segment);\n        sin_Ti = sin(i*theta_per_segment);\n        r_axis0 = -offset[axis_0]*cos_Ti + offset[axis_1]*sin_Ti;\n        r_axis1 = -offset[axis_0]*sin_Ti - offset[axis_1]*cos_Ti;\n        count = 0;\n      }\n  \n      // Update arc_target location\n      position[axis_0] = center_axis0 + r_axis0;\n      position[axis_1] = center_axis1 + r_axis1;\n      position[axis_linear] += linear_per_segment;\n      \n      #ifdef USE_LINE_NUMBERS\n        mc_line(position, feed_rate, invert_feed_rate, line_number);\n      #else\n        mc_line(position, feed_rate, invert_feed_rate);\n      #endif\n      \n      // Bail mid-circle on system abort. Runtime command check already performed by mc_line.\n      if (sys.abort) { return; }\n    }\n  }\n  // Ensure last segment arrives at target location.\n  #ifdef USE_LINE_NUMBERS\n    mc_line(target, feed_rate, invert_feed_rate, line_number);\n  #else\n    mc_line(target, feed_rate, invert_feed_rate);\n  #endif\n}\n\n\n// Execute dwell in seconds.\nvoid mc_dwell(float seconds) \n{\n   if (sys.state == STATE_CHECK_MODE) { return; }\n   \n   uint16_t i = floor(1000/DWELL_TIME_STEP*seconds);\n   protocol_buffer_synchronize();\n   delay_ms(floor(1000*seconds-i*DWELL_TIME_STEP)); // Delay millisecond remainder.\n   while (i-- > 0) {\n     // NOTE: Check and execute realtime commands during dwell every <= DWELL_TIME_STEP milliseconds.\n     protocol_execute_realtime();\n     if (sys.abort) { return; }\n     _delay_ms(DWELL_TIME_STEP); // Delay DWELL_TIME_STEP increment\n   }\n}\n\n\n// Perform homing cycle to locate and set machine zero. Only '$H' executes this command.\n// NOTE: There should be no motions in the buffer and Grbl must be in an idle state before\n// executing the homing cycle. This prevents incorrect buffered plans after homing.\nvoid mc_homing_cycle()\n{\n  // Check and abort homing cycle, if hard limits are already enabled. Helps prevent problems\n  // with machines with limits wired on both ends of travel to one limit pin.\n  // TODO: Move the pin-specific LIMIT_PIN call to limits.c as a function.\n  #ifdef LIMITS_TWO_SWITCHES_ON_AXES  \n    if (limits_get_state()) { \n      mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown.\n      bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT));\n      return;\n    }\n  #endif\n   \n  limits_disable(); // Disable hard limits pin change register for cycle duration\n    \n  // -------------------------------------------------------------------------------------\n  // Perform homing routine. NOTE: Special motion case. Only system reset works.\n  \n  // Search to engage all axes limit switches at faster homing seek rate.\n  limits_go_home(HOMING_CYCLE_0);  // Homing cycle 0\n  #ifdef HOMING_CYCLE_1\n    limits_go_home(HOMING_CYCLE_1);  // Homing cycle 1\n  #endif\n  #ifdef HOMING_CYCLE_2\n    limits_go_home(HOMING_CYCLE_2);  // Homing cycle 2\n  #endif\n    \n  protocol_execute_realtime(); // Check for reset and set system abort.\n  if (sys.abort) { return; } // Did not complete. Alarm state set by mc_alarm.\n\n  // Homing cycle complete! Setup system for normal operation.\n  // -------------------------------------------------------------------------------------\n\n  // Gcode parser position was circumvented by the limits_go_home() routine, so sync position now.\n  gc_sync_position();\n\n  // If hard limits feature enabled, re-enable hard limits pin change register after homing cycle.\n  limits_init();\n}\n\n\n// Perform tool length probe cycle. Requires probe switch.\n// NOTE: Upon probe failure, the program will be stopped and placed into ALARM state.\n#ifdef USE_LINE_NUMBERS\n  void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate, uint8_t is_probe_away, \n    uint8_t is_no_error, int32_t line_number)\n#else\n  void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate, uint8_t is_probe_away,\n    uint8_t is_no_error)\n#endif\n{ \n  // TODO: Need to update this cycle so it obeys a non-auto cycle start.\n  if (sys.state == STATE_CHECK_MODE) { return; }\n\n  // Finish all queued commands and empty planner buffer before starting probe cycle.\n  protocol_buffer_synchronize();\n\n  // Initialize probing control variables\n  sys.probe_succeeded = false; // Re-initialize probe history before beginning cycle.  \n  probe_configure_invert_mask(is_probe_away);\n  \n  // After syncing, check if probe is already triggered. If so, halt and issue alarm.\n  // NOTE: This probe initialization error applies to all probing cycles.\n  if ( probe_get_state() ) { // Check probe pin state.\n    bit_true_atomic(sys.rt_exec_alarm, EXEC_ALARM_PROBE_FAIL);\n    protocol_execute_realtime();\n  }\n  if (sys.abort) { return; } // Return if system reset has been issued.\n\n  // Setup and queue probing motion. Auto cycle-start should not start the cycle.\n  #ifdef USE_LINE_NUMBERS\n    mc_line(target, feed_rate, invert_feed_rate, line_number);\n  #else\n    mc_line(target, feed_rate, invert_feed_rate);\n  #endif\n  \n  // Activate the probing state monitor in the stepper module.\n  sys.probe_state = PROBE_ACTIVE;\n\n  // Perform probing cycle. Wait here until probe is triggered or motion completes.\n  bit_true_atomic(sys.rt_exec_state, EXEC_CYCLE_START);\n  do {\n    protocol_execute_realtime(); \n    if (sys.abort) { return; } // Check for system abort\n  } while (sys.state != STATE_IDLE);\n  \n  // Probing cycle complete!\n  \n  // Set state variables and error out, if the probe failed and cycle with error is enabled.\n  if (sys.probe_state == PROBE_ACTIVE) {\n    if (is_no_error) { memcpy(sys.probe_position, sys.position, sizeof(float)*N_AXIS); }\n    else { bit_true_atomic(sys.rt_exec_alarm, EXEC_ALARM_PROBE_FAIL); }\n  } else { \n    sys.probe_succeeded = true; // Indicate to system the probing cycle completed successfully.\n  }\n  sys.probe_state = PROBE_OFF; // Ensure probe state monitor is disabled.\n  protocol_execute_realtime();   // Check and execute run-time commands\n  if (sys.abort) { return; } // Check for system abort\n\n  // Reset the stepper and planner buffers to remove the remainder of the probe motion.\n  st_reset(); // Reest step segment buffer.\n  plan_reset(); // Reset planner buffer. Zero planner positions. Ensure probing motion is cleared.\n  plan_sync_position(); // Sync planner position to current machine position.\n\n  // TODO: Update the g-code parser code to not require this target calculation but uses a gc_sync_position() call.\n  // NOTE: The target[] variable updated here will be sent back and synced with the g-code parser.\n  system_convert_array_steps_to_mpos(target, sys.position);\n\n  #ifdef MESSAGE_PROBE_COORDINATES\n    // All done! Output the probe position as message.\n    report_probe_parameters();\n  #endif\n}\n\n\n// Method to ready the system to reset by setting the realtime reset command and killing any\n// active processes in the system. This also checks if a system reset is issued while Grbl\n// is in a motion state. If so, kills the steppers and sets the system alarm to flag position\n// lost, since there was an abrupt uncontrolled deceleration. Called at an interrupt level by\n// realtime abort command and hard limits. So, keep to a minimum.\nvoid mc_reset()\n{\n  // Only this function can set the system reset. Helps prevent multiple kill calls.\n  if (bit_isfalse(sys.rt_exec_state, EXEC_RESET)) {\n    bit_true_atomic(sys.rt_exec_state, EXEC_RESET);\n\n    // Kill spindle and coolant.   \n    spindle_stop();\n    coolant_stop();\n\n    // Kill steppers only if in any motion state, i.e. cycle, actively holding, or homing.\n    // NOTE: If steppers are kept enabled via the step idle delay setting, this also keeps\n    // the steppers enabled by avoiding the go_idle call altogether, unless the motion state is\n    // violated, by which, all bets are off.\n    if ((sys.state & (STATE_CYCLE | STATE_HOMING)) || (sys.suspend == SUSPEND_ENABLE_HOLD)) {\n      if (sys.state == STATE_HOMING) { bit_true_atomic(sys.rt_exec_alarm, EXEC_ALARM_HOMING_FAIL); }\n      else { bit_true_atomic(sys.rt_exec_alarm, EXEC_ALARM_ABORT_CYCLE); }\n      st_go_idle(); // Force kill steppers. Position has likely been lost.\n    }\n  }\n}\n"
  },
  {
    "path": "motion_control.h",
    "content": "/*\n  motion_control.h - high level interface for issuing motion commands\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n  \n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef motion_control_h\n#define motion_control_h\n\n\n#define HOMING_CYCLE_LINE_NUMBER -1\n\n// Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second\n// unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in\n// (1 minute)/feed_rate time.\n#ifdef USE_LINE_NUMBERS\nvoid mc_line(float *target, float feed_rate, uint8_t invert_feed_rate, int32_t line_number);\n#else\nvoid mc_line(float *target, float feed_rate, uint8_t invert_feed_rate);\n#endif\n\n// Execute an arc in offset mode format. position == current xyz, target == target xyz, \n// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is\n// the direction of helical travel, radius == circle radius, is_clockwise_arc boolean. Used\n// for vector transformation direction.\n#ifdef USE_LINE_NUMBERS\nvoid mc_arc(float *position, float *target, float *offset, float radius, float feed_rate, \n  uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc, int32_t line_number);\n#else\nvoid mc_arc(float *position, float *target, float *offset, float radius, float feed_rate,\n  uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc);\n#endif\n  \n// Dwell for a specific number of seconds\nvoid mc_dwell(float seconds);\n\n// Perform homing cycle to locate machine zero. Requires limit switches.\nvoid mc_homing_cycle();\n\n// Perform tool length probe cycle. Requires probe switch.\n#ifdef USE_LINE_NUMBERS\nvoid mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate, uint8_t is_probe_away,\n  uint8_t is_no_error, int32_t line_number);\n#else\nvoid mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate, uint8_t is_probe_away,\n  uint8_t is_no_error);\n#endif\n\n// Performs system reset. If in motion state, kills all motion and sets system alarm.\nvoid mc_reset();\n\n#endif\n"
  },
  {
    "path": "nuts_bolts.c",
    "content": "/*\n  nuts_bolts.c - Shared functions\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"grbl.h\"\n\n\n#define MAX_INT_DIGITS 8 // Maximum number of digits in int32 (and float)\n\n\n// Extracts a floating point value from a string. The following code is based loosely on\n// the avr-libc strtod() function by Michael Stumpf and Dmitry Xmelkov and many freely\n// available conversion method examples, but has been highly optimized for Grbl. For known\n// CNC applications, the typical decimal value is expected to be in the range of E0 to E-4.\n// Scientific notation is officially not supported by g-code, and the 'E' character may\n// be a g-code word on some CNC systems. So, 'E' notation will not be recognized. \n// NOTE: Thanks to Radu-Eosif Mihailescu for identifying the issues with using strtod().\nuint8_t read_float(char *line, uint8_t *char_counter, float *float_ptr)                  \n{\n  char *ptr = line + *char_counter;\n  unsigned char c;\n    \n  // Grab first character and increment pointer. No spaces assumed in line.\n  c = *ptr++;\n  \n  // Capture initial positive/minus character\n  bool isnegative = false;\n  if (c == '-') {\n    isnegative = true;\n    c = *ptr++;\n  } else if (c == '+') {\n    c = *ptr++;\n  }\n  \n  // Extract number into fast integer. Track decimal in terms of exponent value.\n  uint32_t intval = 0;\n  int8_t exp = 0;\n  uint8_t ndigit = 0;\n  bool isdecimal = false;\n  while(1) {\n    c -= '0';\n    if (c <= 9) {\n      ndigit++;\n      if (ndigit <= MAX_INT_DIGITS) {\n        if (isdecimal) { exp--; }\n        intval = (((intval << 2) + intval) << 1) + c; // intval*10 + c\n      } else {\n        if (!(isdecimal)) { exp++; }  // Drop overflow digits\n      }\n    } else if (c == (('.'-'0') & 0xff)  &&  !(isdecimal)) {\n      isdecimal = true;\n    } else {\n      break;\n    }\n    c = *ptr++;\n  }\n  \n  // Return if no digits have been read.\n  if (!ndigit) { return(false); };\n  \n  // Convert integer into floating point.\n  float fval;\n  fval = (float)intval;\n  \n  // Apply decimal. Should perform no more than two floating point multiplications for the\n  // expected range of E0 to E-4.\n  if (fval != 0) {\n    while (exp <= -2) {\n      fval *= 0.01; \n      exp += 2;\n    }\n    if (exp < 0) { \n      fval *= 0.1; \n    } else if (exp > 0) {\n      do {\n        fval *= 10.0;\n      } while (--exp > 0);\n    } \n  }\n\n  // Assign floating point value with correct sign.    \n  if (isnegative) {\n    *float_ptr = -fval;\n  } else {\n    *float_ptr = fval;\n  }\n\n  *char_counter = ptr - line - 1; // Set char_counter to next statement\n  \n  return(true);\n}\n\n\n// Delays variable defined milliseconds. Compiler compatibility fix for _delay_ms(),\n// which only accepts constants in future compiler releases.\nvoid delay_ms(uint16_t ms) \n{\n  while ( ms-- ) { _delay_ms(1); }\n}\n\n\n// Delays variable defined microseconds. Compiler compatibility fix for _delay_us(),\n// which only accepts constants in future compiler releases. Written to perform more \n// efficiently with larger delays, as the counter adds parasitic time in each iteration.\nvoid delay_us(uint32_t us) \n{\n  while (us) {\n    if (us < 10) { \n      _delay_us(1);\n      us--;\n    } else if (us < 100) {\n      _delay_us(10);\n      us -= 10;\n    } else if (us < 1000) {\n      _delay_us(100);\n      us -= 100;\n    } else {\n      _delay_ms(1);\n      us -= 1000;\n    }\n  }\n}\n\n\n// Simple hypotenuse computation function.\nfloat hypot_f(float x, float y) { return(sqrt(x*x + y*y)); }\n"
  },
  {
    "path": "nuts_bolts.h",
    "content": "/*\n  nuts_bolts.h - Header file for shared definitions, variables, and functions\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon \n  Copyright (c) 2009-2011 Simen Svale Skogsrud \n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef nuts_bolts_h\n#define nuts_bolts_h\n\n#define false 0\n#define true 1\n\n// Axis array index values. Must start with 0 and be continuous.\n#define N_AXIS 3 // Number of axes\n#define X_AXIS 0 // Axis indexing value. \n#define Y_AXIS 1\n#define Z_AXIS 2\n// #define A_AXIS 3\n\n// CoreXY motor assignments. DO NOT ALTER.\n// NOTE: If the A and B motor axis bindings are changed, this effects the CoreXY equations.\n#ifdef COREXY\n #define A_MOTOR X_AXIS // Must be X_AXIS\n #define B_MOTOR Y_AXIS // Must be Y_AXIS\n#endif\n\n// Conversions\n#define MM_PER_INCH (25.40)\n#define INCH_PER_MM (0.0393701)\n#define TICKS_PER_MICROSECOND (F_CPU/1000000)\n\n// Useful macros\n#define clear_vector(a) memset(a, 0, sizeof(a))\n#define clear_vector_float(a) memset(a, 0.0, sizeof(float)*N_AXIS)\n// #define clear_vector_long(a) memset(a, 0.0, sizeof(long)*N_AXIS)\n#define max(a,b) (((a) > (b)) ? (a) : (b))\n#define min(a,b) (((a) < (b)) ? (a) : (b))\n\n// Bit field and masking macros\n#define bit(n) (1 << n) \n#define bit_true_atomic(x,mask) {uint8_t sreg = SREG; cli(); (x) |= (mask); SREG = sreg; }\n#define bit_false_atomic(x,mask) {uint8_t sreg = SREG; cli(); (x) &= ~(mask); SREG = sreg; }\n#define bit_toggle_atomic(x,mask) {uint8_t sreg = SREG; cli(); (x) ^= (mask); SREG = sreg; }\n#define bit_true(x,mask) (x) |= (mask)\n#define bit_false(x,mask) (x) &= ~(mask)\n#define bit_istrue(x,mask) ((x & mask) != 0)\n#define bit_isfalse(x,mask) ((x & mask) == 0)\n\n// Read a floating point value from a string. Line points to the input buffer, char_counter \n// is the indexer pointing to the current character of the line, while float_ptr is \n// a pointer to the result variable. Returns true when it succeeds\nuint8_t read_float(char *line, uint8_t *char_counter, float *float_ptr);\n\n// Delays variable-defined milliseconds. Compiler compatibility fix for _delay_ms().\nvoid delay_ms(uint16_t ms);\n\n// Delays variable-defined microseconds. Compiler compatibility fix for _delay_us().\nvoid delay_us(uint32_t us);\n\n// Computes hypotenuse, avoiding avr-gcc's bloated version and the extra error checking.\nfloat hypot_f(float x, float y);\n\n#endif\n"
  },
  {
    "path": "planner.c",
    "content": "/*\n  planner.c - buffers movement commands and manages the acceleration profile plan\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud \n  Copyright (c) 2011 Jens Geisler \n  \n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"grbl.h\"\n\n#define SOME_LARGE_VALUE 1.0E+38 // Used by rapids and acceleration maximization calculations. Just needs\n                                 // to be larger than any feasible (mm/min)^2 or mm/sec^2 value.\n\nstatic plan_block_t block_buffer[BLOCK_BUFFER_SIZE];  // A ring buffer for motion instructions\nstatic uint8_t block_buffer_tail;     // Index of the block to process now\nstatic uint8_t block_buffer_head;     // Index of the next block to be pushed\nstatic uint8_t next_buffer_head;      // Index of the next buffer head\nstatic uint8_t block_buffer_planned;  // Index of the optimally planned block\n\n// Define planner variables\ntypedef struct {\n  int32_t position[N_AXIS];          // The planner position of the tool in absolute steps. Kept separate\n                                     // from g-code position for movements requiring multiple line motions,\n                                     // i.e. arcs, canned cycles, and backlash compensation.\n  float previous_unit_vec[N_AXIS];   // Unit vector of previous path line segment\n  float previous_nominal_speed_sqr;  // Nominal speed of previous path line segment\n} planner_t;\nstatic planner_t pl;\n\n\n// Returns the index of the next block in the ring buffer. Also called by stepper segment buffer.\nuint8_t plan_next_block_index(uint8_t block_index) \n{\n  block_index++;\n  if (block_index == BLOCK_BUFFER_SIZE) { block_index = 0; }\n  return(block_index);\n}\n\n\n// Returns the index of the previous block in the ring buffer\nstatic uint8_t plan_prev_block_index(uint8_t block_index) \n{\n  if (block_index == 0) { block_index = BLOCK_BUFFER_SIZE; }\n  block_index--;\n  return(block_index);\n}\n\n\n/*                            PLANNER SPEED DEFINITION                                              \n                                     +--------+   <- current->nominal_speed\n                                    /          \\                                \n         current->entry_speed ->   +            \\                               \n                                   |             + <- next->entry_speed (aka exit speed)\n                                   +-------------+                              \n                                       time -->                      \n                                                  \n  Recalculates the motion plan according to the following basic guidelines:\n  \n    1. Go over every feasible block sequentially in reverse order and calculate the junction speeds\n        (i.e. current->entry_speed) such that:\n      a. No junction speed exceeds the pre-computed maximum junction speed limit or nominal speeds of \n         neighboring blocks.\n      b. A block entry speed cannot exceed one reverse-computed from its exit speed (next->entry_speed)\n         with a maximum allowable deceleration over the block travel distance.\n      c. The last (or newest appended) block is planned from a complete stop (an exit speed of zero).\n    2. Go over every block in chronological (forward) order and dial down junction speed values if \n      a. The exit speed exceeds the one forward-computed from its entry speed with the maximum allowable\n         acceleration over the block travel distance.\n  \n  When these stages are complete, the planner will have maximized the velocity profiles throughout the all\n  of the planner blocks, where every block is operating at its maximum allowable acceleration limits. In \n  other words, for all of the blocks in the planner, the plan is optimal and no further speed improvements\n  are possible. If a new block is added to the buffer, the plan is recomputed according to the said \n  guidelines for a new optimal plan.\n  \n  To increase computational efficiency of these guidelines, a set of planner block pointers have been\n  created to indicate stop-compute points for when the planner guidelines cannot logically make any further\n  changes or improvements to the plan when in normal operation and new blocks are streamed and added to the\n  planner buffer. For example, if a subset of sequential blocks in the planner have been planned and are \n  bracketed by junction velocities at their maximums (or by the first planner block as well), no new block\n  added to the planner buffer will alter the velocity profiles within them. So we no longer have to compute\n  them. Or, if a set of sequential blocks from the first block in the planner (or a optimal stop-compute\n  point) are all accelerating, they are all optimal and can not be altered by a new block added to the\n  planner buffer, as this will only further increase the plan speed to chronological blocks until a maximum\n  junction velocity is reached. However, if the operational conditions of the plan changes from infrequently\n  used feed holds or feedrate overrides, the stop-compute pointers will be reset and the entire plan is  \n  recomputed as stated in the general guidelines.\n  \n  Planner buffer index mapping:\n  - block_buffer_tail: Points to the beginning of the planner buffer. First to be executed or being executed. \n  - block_buffer_head: Points to the buffer block after the last block in the buffer. Used to indicate whether\n      the buffer is full or empty. As described for standard ring buffers, this block is always empty.\n  - next_buffer_head: Points to next planner buffer block after the buffer head block. When equal to the \n      buffer tail, this indicates the buffer is full.\n  - block_buffer_planned: Points to the first buffer block after the last optimally planned block for normal\n      streaming operating conditions. Use for planning optimizations by avoiding recomputing parts of the \n      planner buffer that don't change with the addition of a new block, as describe above. In addition, \n      this block can never be less than block_buffer_tail and will always be pushed forward and maintain \n      this requirement when encountered by the plan_discard_current_block() routine during a cycle.\n  \n  NOTE: Since the planner only computes on what's in the planner buffer, some motions with lots of short \n  line segments, like G2/3 arcs or complex curves, may seem to move slow. This is because there simply isn't\n  enough combined distance traveled in the entire buffer to accelerate up to the nominal speed and then \n  decelerate to a complete stop at the end of the buffer, as stated by the guidelines. If this happens and\n  becomes an annoyance, there are a few simple solutions: (1) Maximize the machine acceleration. The planner\n  will be able to compute higher velocity profiles within the same combined distance. (2) Maximize line \n  motion(s) distance per block to a desired tolerance. The more combined distance the planner has to use,\n  the faster it can go. (3) Maximize the planner buffer size. This also will increase the combined distance\n  for the planner to compute over. It also increases the number of computations the planner has to perform\n  to compute an optimal plan, so select carefully. The Arduino 328p memory is already maxed out, but future\n  ARM versions should have enough memory and speed for look-ahead blocks numbering up to a hundred or more.\n\n*/\nstatic void planner_recalculate() \n{   \n  // Initialize block index to the last block in the planner buffer.\n  uint8_t block_index = plan_prev_block_index(block_buffer_head);\n        \n  // Bail. Can't do anything with one only one plan-able block.\n  if (block_index == block_buffer_planned) { return; }\n      \n  // Reverse Pass: Coarsely maximize all possible deceleration curves back-planning from the last\n  // block in buffer. Cease planning when the last optimal planned or tail pointer is reached.\n  // NOTE: Forward pass will later refine and correct the reverse pass to create an optimal plan.\n  float entry_speed_sqr;\n  plan_block_t *next;\n  plan_block_t *current = &block_buffer[block_index];\n\n  // Calculate maximum entry speed for last block in buffer, where the exit speed is always zero.\n  current->entry_speed_sqr = min( current->max_entry_speed_sqr, 2*current->acceleration*current->millimeters);\n  \n  block_index = plan_prev_block_index(block_index);\n  if (block_index == block_buffer_planned) { // Only two plannable blocks in buffer. Reverse pass complete.\n    // Check if the first block is the tail. If so, notify stepper to update its current parameters.\n    if (block_index == block_buffer_tail) { st_update_plan_block_parameters(); }\n  } else { // Three or more plan-able blocks\n    while (block_index != block_buffer_planned) { \n      next = current;\n      current = &block_buffer[block_index];\n      block_index = plan_prev_block_index(block_index);\n\n      // Check if next block is the tail block(=planned block). If so, update current stepper parameters.\n      if (block_index == block_buffer_tail) { st_update_plan_block_parameters(); } \n\n      // Compute maximum entry speed decelerating over the current block from its exit speed.\n      if (current->entry_speed_sqr != current->max_entry_speed_sqr) {\n        entry_speed_sqr = next->entry_speed_sqr + 2*current->acceleration*current->millimeters;\n        if (entry_speed_sqr < current->max_entry_speed_sqr) {\n          current->entry_speed_sqr = entry_speed_sqr;\n        } else {\n          current->entry_speed_sqr = current->max_entry_speed_sqr;\n        }\n      }\n    }\n  }    \n\n  // Forward Pass: Forward plan the acceleration curve from the planned pointer onward.\n  // Also scans for optimal plan breakpoints and appropriately updates the planned pointer.\n  next = &block_buffer[block_buffer_planned]; // Begin at buffer planned pointer\n  block_index = plan_next_block_index(block_buffer_planned); \n  while (block_index != block_buffer_head) {\n    current = next;\n    next = &block_buffer[block_index];\n    \n    // Any acceleration detected in the forward pass automatically moves the optimal planned\n    // pointer forward, since everything before this is all optimal. In other words, nothing\n    // can improve the plan from the buffer tail to the planned pointer by logic.\n    if (current->entry_speed_sqr < next->entry_speed_sqr) {\n      entry_speed_sqr = current->entry_speed_sqr + 2*current->acceleration*current->millimeters;\n      // If true, current block is full-acceleration and we can move the planned pointer forward.\n      if (entry_speed_sqr < next->entry_speed_sqr) {\n        next->entry_speed_sqr = entry_speed_sqr; // Always <= max_entry_speed_sqr. Backward pass sets this.\n        block_buffer_planned = block_index; // Set optimal plan pointer.\n      }\n    }\n    \n    // Any block set at its maximum entry speed also creates an optimal plan up to this\n    // point in the buffer. When the plan is bracketed by either the beginning of the\n    // buffer and a maximum entry speed or two maximum entry speeds, every block in between\n    // cannot logically be further improved. Hence, we don't have to recompute them anymore.\n    if (next->entry_speed_sqr == next->max_entry_speed_sqr) { block_buffer_planned = block_index; }\n    block_index = plan_next_block_index( block_index );\n  } \n}\n\n\nvoid plan_reset() \n{\n  memset(&pl, 0, sizeof(pl)); // Clear planner struct\n  block_buffer_tail = 0;\n  block_buffer_head = 0; // Empty = tail\n  next_buffer_head = 1; // plan_next_block_index(block_buffer_head)\n  block_buffer_planned = 0; // = block_buffer_tail;\n}\n\n\nvoid plan_discard_current_block() \n{\n  if (block_buffer_head != block_buffer_tail) { // Discard non-empty buffer.\n    uint8_t block_index = plan_next_block_index( block_buffer_tail );\n    // Push block_buffer_planned pointer, if encountered.\n    if (block_buffer_tail == block_buffer_planned) { block_buffer_planned = block_index; }\n    block_buffer_tail = block_index;\n  }\n}\n\n\nplan_block_t *plan_get_current_block() \n{\n  if (block_buffer_head == block_buffer_tail) { return(NULL); } // Buffer empty  \n  return(&block_buffer[block_buffer_tail]);\n}\n\n\nfloat plan_get_exec_block_exit_speed()\n{\n  uint8_t block_index = plan_next_block_index(block_buffer_tail);\n  if (block_index == block_buffer_head) { return( 0.0 ); }\n  return( sqrt( block_buffer[block_index].entry_speed_sqr ) ); \n}\n\n\n// Returns the availability status of the block ring buffer. True, if full.\nuint8_t plan_check_full_buffer()\n{\n  if (block_buffer_tail == next_buffer_head) { return(true); }\n  return(false);\n}\n\n\n/* Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position\n   in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed\n   rate is taken to mean \"frequency\" and would complete the operation in 1/feed_rate minutes.\n   All position data passed to the planner must be in terms of machine position to keep the planner \n   independent of any coordinate system changes and offsets, which are handled by the g-code parser.\n   NOTE: Assumes buffer is available. Buffer checks are handled at a higher level by motion_control.\n   In other words, the buffer head is never equal to the buffer tail.  Also the feed rate input value\n   is used in three ways: as a normal feed rate if invert_feed_rate is false, as inverse time if\n   invert_feed_rate is true, or as seek/rapids rate if the feed_rate value is negative (and\n   invert_feed_rate always false). */\n#ifdef USE_LINE_NUMBERS   \n  void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate, int32_t line_number) \n#else\n  void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate) \n#endif\n{\n  // Prepare and initialize new block\n  plan_block_t *block = &block_buffer[block_buffer_head];\n  block->step_event_count = 0;\n  block->millimeters = 0;\n  block->direction_bits = 0;\n  block->acceleration = SOME_LARGE_VALUE; // Scaled down to maximum acceleration later\n  #ifdef USE_LINE_NUMBERS\n    block->line_number = line_number;\n  #endif\n\n  // Compute and store initial move distance data.\n  // TODO: After this for-loop, we don't touch the stepper algorithm data. Might be a good idea\n  // to try to keep these types of things completely separate from the planner for portability.\n  int32_t target_steps[N_AXIS];\n  float unit_vec[N_AXIS], delta_mm;\n  uint8_t idx;\n  #ifdef COREXY\n    target_steps[A_MOTOR] = lround(target[A_MOTOR]*settings.steps_per_mm[A_MOTOR]);\n    target_steps[B_MOTOR] = lround(target[B_MOTOR]*settings.steps_per_mm[B_MOTOR]);\n    block->steps[A_MOTOR] = labs((target_steps[X_AXIS]-pl.position[X_AXIS]) + (target_steps[Y_AXIS]-pl.position[Y_AXIS]));\n    block->steps[B_MOTOR] = labs((target_steps[X_AXIS]-pl.position[X_AXIS]) - (target_steps[Y_AXIS]-pl.position[Y_AXIS]));\n  #endif\n\n  for (idx=0; idx<N_AXIS; idx++) {\n    // Calculate target position in absolute steps, number of steps for each axis, and determine max step events.\n    // Also, compute individual axes distance for move and prep unit vector calculations.\n    // NOTE: Computes true distance from converted step values.\n    #ifdef COREXY\n      if ( !(idx == A_MOTOR) && !(idx == B_MOTOR) ) {\n        target_steps[idx] = lround(target[idx]*settings.steps_per_mm[idx]);\n        block->steps[idx] = labs(target_steps[idx]-pl.position[idx]);\n      }\n      block->step_event_count = max(block->step_event_count, block->steps[idx]);\n      if (idx == A_MOTOR) {\n        delta_mm = ((target_steps[X_AXIS]-pl.position[X_AXIS]) + (target_steps[Y_AXIS]-pl.position[Y_AXIS]))/settings.steps_per_mm[idx];\n      } else if (idx == B_MOTOR) {\n        delta_mm = ((target_steps[X_AXIS]-pl.position[X_AXIS]) - (target_steps[Y_AXIS]-pl.position[Y_AXIS]))/settings.steps_per_mm[idx];\n      } else {\n        delta_mm = (target_steps[idx] - pl.position[idx])/settings.steps_per_mm[idx];\n      }\n    #else\n      target_steps[idx] = lround(target[idx]*settings.steps_per_mm[idx]);\n      block->steps[idx] = labs(target_steps[idx]-pl.position[idx]);\n      block->step_event_count = max(block->step_event_count, block->steps[idx]);\n      delta_mm = (target_steps[idx] - pl.position[idx])/settings.steps_per_mm[idx];\n    #endif\n    unit_vec[idx] = delta_mm; // Store unit vector numerator. Denominator computed later.\n        \n    // Set direction bits. Bit enabled always means direction is negative.\n    if (delta_mm < 0 ) { block->direction_bits |= get_direction_pin_mask(idx); }\n    \n    // Incrementally compute total move distance by Euclidean norm. First add square of each term.\n    block->millimeters += delta_mm*delta_mm;\n  }\n  block->millimeters = sqrt(block->millimeters); // Complete millimeters calculation with sqrt()\n  \n  // Bail if this is a zero-length block. Highly unlikely to occur.\n  if (block->step_event_count == 0) { return; } \n  \n  // Adjust feed_rate value to mm/min depending on type of rate input (normal, inverse time, or rapids)\n  // TODO: Need to distinguish a rapids vs feed move for overrides. Some flag of some sort.\n  if (feed_rate < 0) { feed_rate = SOME_LARGE_VALUE; } // Scaled down to absolute max/rapids rate later\n  else if (invert_feed_rate) { feed_rate *= block->millimeters; }\n  if (feed_rate < MINIMUM_FEED_RATE) { feed_rate = MINIMUM_FEED_RATE; } // Prevents step generation round-off condition.\n\n  // Calculate the unit vector of the line move and the block maximum feed rate and acceleration scaled \n  // down such that no individual axes maximum values are exceeded with respect to the line direction. \n  // NOTE: This calculation assumes all axes are orthogonal (Cartesian) and works with ABC-axes,\n  // if they are also orthogonal/independent. Operates on the absolute value of the unit vector.\n  float inverse_unit_vec_value;\n  float inverse_millimeters = 1.0/block->millimeters;  // Inverse millimeters to remove multiple float divides\t\n  float junction_cos_theta = 0;\n  for (idx=0; idx<N_AXIS; idx++) {\n    if (unit_vec[idx] != 0) {  // Avoid divide by zero.\n      unit_vec[idx] *= inverse_millimeters;  // Complete unit vector calculation\n      inverse_unit_vec_value = fabs(1.0/unit_vec[idx]); // Inverse to remove multiple float divides.\n\n      // Check and limit feed rate against max individual axis velocities and accelerations\n      feed_rate = min(feed_rate,settings.max_rate[idx]*inverse_unit_vec_value);\n      block->acceleration = min(block->acceleration,settings.acceleration[idx]*inverse_unit_vec_value);\n\n      // Incrementally compute cosine of angle between previous and current path. Cos(theta) of the junction\n      // between the current move and the previous move is simply the dot product of the two unit vectors, \n      // where prev_unit_vec is negative. Used later to compute maximum junction speed.\n      junction_cos_theta -= pl.previous_unit_vec[idx] * unit_vec[idx];\n    }\n  }\n  \n  // TODO: Need to check this method handling zero junction speeds when starting from rest.\n  if (block_buffer_head == block_buffer_tail) {\n  \n    // Initialize block entry speed as zero. Assume it will be starting from rest. Planner will correct this later.\n    block->entry_speed_sqr = 0.0;\n    block->max_junction_speed_sqr = 0.0; // Starting from rest. Enforce start from zero velocity.\n  \n  } else {\n    /* \n       Compute maximum allowable entry speed at junction by centripetal acceleration approximation.\n       Let a circle be tangent to both previous and current path line segments, where the junction \n       deviation is defined as the distance from the junction to the closest edge of the circle, \n       colinear with the circle center. The circular segment joining the two paths represents the \n       path of centripetal acceleration. Solve for max velocity based on max acceleration about the\n       radius of the circle, defined indirectly by junction deviation. This may be also viewed as \n       path width or max_jerk in the previous Grbl version. This approach does not actually deviate \n       from path, but used as a robust way to compute cornering speeds, as it takes into account the\n       nonlinearities of both the junction angle and junction velocity.\n\n       NOTE: If the junction deviation value is finite, Grbl executes the motions in an exact path \n       mode (G61). If the junction deviation value is zero, Grbl will execute the motion in an exact\n       stop mode (G61.1) manner. In the future, if continuous mode (G64) is desired, the math here\n       is exactly the same. Instead of motioning all the way to junction point, the machine will\n       just follow the arc circle defined here. The Arduino doesn't have the CPU cycles to perform\n       a continuous mode path, but ARM-based microcontrollers most certainly do. \n       \n       NOTE: The max junction speed is a fixed value, since machine acceleration limits cannot be\n       changed dynamically during operation nor can the line move geometry. This must be kept in\n       memory in the event of a feedrate override changing the nominal speeds of blocks, which can \n       change the overall maximum entry speed conditions of all blocks.\n    */\n    // NOTE: Computed without any expensive trig, sin() or acos(), by trig half angle identity of cos(theta).\n    if (junction_cos_theta > 0.99) {\n      //  For a 0 degree acute junction, just set minimum junction speed. \n      block->max_junction_speed_sqr = MINIMUM_JUNCTION_SPEED*MINIMUM_JUNCTION_SPEED;\n    } else {\n      junction_cos_theta = max(junction_cos_theta,-0.99); // Check for numerical round-off to avoid divide by zero.\n      float sin_theta_d2 = sqrt(0.5*(1.0-junction_cos_theta)); // Trig half angle identity. Always positive.\n\n      // TODO: Technically, the acceleration used in calculation needs to be limited by the minimum of the\n      // two junctions. However, this shouldn't be a significant problem except in extreme circumstances.\n      block->max_junction_speed_sqr = max( MINIMUM_JUNCTION_SPEED*MINIMUM_JUNCTION_SPEED,\n                                   (block->acceleration * settings.junction_deviation * sin_theta_d2)/(1.0-sin_theta_d2) );\n\n    }\n  }\n\n  // Store block nominal speed\n  block->nominal_speed_sqr = feed_rate*feed_rate; // (mm/min). Always > 0\n  \n  // Compute the junction maximum entry based on the minimum of the junction speed and neighboring nominal speeds.\n  block->max_entry_speed_sqr = min(block->max_junction_speed_sqr, \n                                   min(block->nominal_speed_sqr,pl.previous_nominal_speed_sqr));\n  \n  // Update previous path unit_vector and nominal speed (squared)\n  memcpy(pl.previous_unit_vec, unit_vec, sizeof(unit_vec)); // pl.previous_unit_vec[] = unit_vec[]\n  pl.previous_nominal_speed_sqr = block->nominal_speed_sqr;\n    \n  // Update planner position\n  memcpy(pl.position, target_steps, sizeof(target_steps)); // pl.position[] = target_steps[]\n\n  // New block is all set. Update buffer head and next buffer head indices.\n  block_buffer_head = next_buffer_head;  \n  next_buffer_head = plan_next_block_index(block_buffer_head);\n  \n  // Finish up by recalculating the plan with the new block.\n  planner_recalculate();\n}\n\n\n// Reset the planner position vectors. Called by the system abort/initialization routine.\nvoid plan_sync_position()\n{\n  // TODO: For motor configurations not in the same coordinate frame as the machine position,\n  // this function needs to be updated to accomodate the difference. \n  uint8_t idx;\n  for (idx=0; idx<N_AXIS; idx++) {\n    #ifdef COREXY\n     if (idx==A_MOTOR) { \n        pl.position[idx] = (sys.position[A_MOTOR] + sys.position[B_MOTOR])/2;\n      } else if (idx==B_MOTOR) { \n        pl.position[idx] = (sys.position[A_MOTOR] - sys.position[B_MOTOR])/2;\n      } else {\n        pl.position[idx] = sys.position[idx];\n      }\n    #else\n      pl.position[idx] = sys.position[idx];\n    #endif\n  }\n}\n\n\n// Returns the number of active blocks are in the planner buffer.\nuint8_t plan_get_block_buffer_count()\n{\n  if (block_buffer_head >= block_buffer_tail) { return(block_buffer_head-block_buffer_tail); }\n  return(BLOCK_BUFFER_SIZE - (block_buffer_tail-block_buffer_head));\n}\n\n\n// Re-initialize buffer plan with a partially completed block, assumed to exist at the buffer tail.\n// Called after a steppers have come to a complete stop for a feed hold and the cycle is stopped.\nvoid plan_cycle_reinitialize()\n{\n  // Re-plan from a complete stop. Reset planner entry speeds and buffer planned pointer.\n  st_update_plan_block_parameters();\n  block_buffer_planned = block_buffer_tail;\n  planner_recalculate();  \n}\n"
  },
  {
    "path": "planner.h",
    "content": "/*\n  planner.h - buffers movement commands and manages the acceleration profile plan\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon \n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef planner_h\n#define planner_h\n\n\n// The number of linear motions that can be in the plan at any give time\n#ifndef BLOCK_BUFFER_SIZE\n  #ifdef USE_LINE_NUMBERS\n    #define BLOCK_BUFFER_SIZE 16\n  #else\n    #define BLOCK_BUFFER_SIZE 18\n  #endif\n#endif\n\n// This struct stores a linear movement of a g-code block motion with its critical \"nominal\" values\n// are as specified in the source g-code. \ntypedef struct {\n  // Fields used by the bresenham algorithm for tracing the line\n  // NOTE: Used by stepper algorithm to execute the block correctly. Do not alter these values.\n  uint8_t direction_bits;    // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)\n  uint32_t steps[N_AXIS];    // Step count along each axis\n  uint32_t step_event_count; // The maximum step axis count and number of steps required to complete this block. \n\n  // Fields used by the motion planner to manage acceleration\n  float entry_speed_sqr;         // The current planned entry speed at block junction in (mm/min)^2\n  float max_entry_speed_sqr;     // Maximum allowable entry speed based on the minimum of junction limit and \n                                 //   neighboring nominal speeds with overrides in (mm/min)^2\n  float max_junction_speed_sqr;  // Junction entry speed limit based on direction vectors in (mm/min)^2\n  float nominal_speed_sqr;       // Axis-limit adjusted nominal speed for this block in (mm/min)^2\n  float acceleration;            // Axis-limit adjusted line acceleration in (mm/min^2)\n  float millimeters;             // The remaining distance for this block to be executed in (mm)\n  // uint8_t max_override;       // Maximum override value based on axis speed limits\n\n  #ifdef USE_LINE_NUMBERS\n    int32_t line_number;\n  #endif\n} plan_block_t;\n\n      \n// Initialize and reset the motion plan subsystem\nvoid plan_reset();\n\n// Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position \n// in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed\n// rate is taken to mean \"frequency\" and would complete the operation in 1/feed_rate minutes.\n#ifdef USE_LINE_NUMBERS\n  void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate, int32_t line_number);\n#else\n  void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate);\n#endif\n\n// Called when the current block is no longer needed. Discards the block and makes the memory\n// availible for new blocks.\nvoid plan_discard_current_block();\n\n// Gets the current block. Returns NULL if buffer empty\nplan_block_t *plan_get_current_block();\n\n// Called periodically by step segment buffer. Mostly used internally by planner.\nuint8_t plan_next_block_index(uint8_t block_index);\n\n// Called by step segment buffer when computing executing block velocity profile.\nfloat plan_get_exec_block_exit_speed();\n\n// Reset the planner position vector (in steps)\nvoid plan_sync_position();\n\n// Reinitialize plan with a partially completed block\nvoid plan_cycle_reinitialize();\n\n// Returns the number of active blocks are in the planner buffer.\nuint8_t plan_get_block_buffer_count();\n\n// Returns the status of the block ring buffer. True, if buffer is full.\nuint8_t plan_check_full_buffer();\n\n#endif\n"
  },
  {
    "path": "print.c",
    "content": "/*\n  print.c - Functions for formatting output strings\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"grbl.h\"\n\n\nvoid printString(const char *s)\n{\n  while (*s)\n    serial_write(*s++);\n}\n\n\n// Print a string stored in PGM-memory\nvoid printPgmString(const char *s)\n{\n  char c;\n  while ((c = pgm_read_byte_near(s++)))\n    serial_write(c);\n}\n\n\n// void printIntegerInBase(unsigned long n, unsigned long base)\n// { \n// \tunsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. \n// \tunsigned long i = 0;\n// \n// \tif (n == 0) {\n// \t\tserial_write('0');\n// \t\treturn;\n// \t} \n// \n// \twhile (n > 0) {\n// \t\tbuf[i++] = n % base;\n// \t\tn /= base;\n// \t}\n// \n// \tfor (; i > 0; i--)\n// \t\tserial_write(buf[i - 1] < 10 ?\n// \t\t\t'0' + buf[i - 1] :\n// \t\t\t'A' + buf[i - 1] - 10);\n// }\n\n\n// Prints an uint8 variable with base and number of desired digits.\nvoid print_unsigned_int8(uint8_t n, uint8_t base, uint8_t digits)\n{ \n  unsigned char buf[digits];\n  uint8_t i = 0;\n\n  for (; i < digits; i++) {\n      buf[i] = n % base ;\n      n /= base;\n  }\n\n  for (; i > 0; i--)\n      serial_write('0' + buf[i - 1]);\n}\n\n\n// Prints an uint8 variable in base 2.\nvoid print_uint8_base2(uint8_t n) {\n  print_unsigned_int8(n,2,8);\n}\n\n\n// Prints an uint8 variable in base 10.\nvoid print_uint8_base10(uint8_t n)\n{   \n  uint8_t digits;\n  if (n < 10) { digits = 1; } \n  else if (n < 100) { digits = 2; }\n  else { digits = 3; }\n  print_unsigned_int8(n,10,digits);\n}\n\n\nvoid print_uint32_base10(uint32_t n)\n{ \n  if (n == 0) {\n    serial_write('0');\n    return;\n  } \n\n  unsigned char buf[10]; \n  uint8_t i = 0;  \n  \n  while (n > 0) {\n    buf[i++] = n % 10;\n    n /= 10;\n  }\n    \n  for (; i > 0; i--)\n    serial_write('0' + buf[i-1]);\n}\n\n\nvoid printInteger(long n)\n{\n  if (n < 0) {\n    serial_write('-');\n    print_uint32_base10(-n);\n  } else {\n    print_uint32_base10(n);\n  }\n}\n\n\n// Convert float to string by immediately converting to a long integer, which contains\n// more digits than a float. Number of decimal places, which are tracked by a counter,\n// may be set by the user. The integer is then efficiently converted to a string.\n// NOTE: AVR '%' and '/' integer operations are very efficient. Bitshifting speed-up \n// techniques are actually just slightly slower. Found this out the hard way.\nvoid printFloat(float n, uint8_t decimal_places)\n{\n  if (n < 0) {\n    serial_write('-');\n    n = -n;\n  }\n\n  uint8_t decimals = decimal_places;\n  while (decimals >= 2) { // Quickly convert values expected to be E0 to E-4.\n    n *= 100;\n    decimals -= 2;\n  }\n  if (decimals) { n *= 10; }\n  n += 0.5; // Add rounding factor. Ensures carryover through entire value.\n    \n  // Generate digits backwards and store in string.\n  unsigned char buf[10]; \n  uint8_t i = 0;\n  uint32_t a = (long)n;  \n  buf[decimal_places] = '.'; // Place decimal point, even if decimal places are zero.\n  while(a > 0) {\n    if (i == decimal_places) { i++; } // Skip decimal point location\n    buf[i++] = (a % 10) + '0'; // Get digit\n    a /= 10;\n  }\n  while (i < decimal_places) { \n     buf[i++] = '0'; // Fill in zeros to decimal point for (n < 1)\n  }\n  if (i == decimal_places) { // Fill in leading zero, if needed.\n    i++;\n    buf[i++] = '0'; \n  }   \n  \n  // Print the generated string.\n  for (; i > 0; i--)\n    serial_write(buf[i-1]);\n}\n\n\n// Floating value printing handlers for special variables types used in Grbl and are defined\n// in the config.h.\n//  - CoordValue: Handles all position or coordinate values in inches or mm reporting.\n//  - RateValue: Handles feed rate and current velocity in inches or mm reporting.\n//  - SettingValue: Handles all floating point settings values (always in mm.)\nvoid printFloat_CoordValue(float n) { \n  if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { \n    printFloat(n*INCH_PER_MM,N_DECIMAL_COORDVALUE_INCH);\n  } else {\n    printFloat(n,N_DECIMAL_COORDVALUE_MM);\n  }\n}\n\nvoid printFloat_RateValue(float n) { \n  if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {\n    printFloat(n*INCH_PER_MM,N_DECIMAL_RATEVALUE_INCH);\n  } else {\n    printFloat(n,N_DECIMAL_RATEVALUE_MM);\n  }\n}\n\nvoid printFloat_SettingValue(float n) { printFloat(n,N_DECIMAL_SETTINGVALUE); }\n\n\n// Debug tool to print free memory in bytes at the called point. \n// NOTE: Keep commented unless using. Part of this function always gets compiled in.\n// void printFreeMemory()\n// {\n//   extern int __heap_start, *__brkval; \n//   uint16_t free;  // Up to 64k values.\n//   free = (int) &free - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); \n//   printInteger((int32_t)free);\n//   printString(\" \");\n// }\n"
  },
  {
    "path": "print.h",
    "content": "/*\n  print.h - Functions for formatting output strings\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef print_h\n#define print_h\n\n\nvoid printString(const char *s);\n\nvoid printPgmString(const char *s);\n\nvoid printInteger(long n);\n\nvoid print_uint32_base10(uint32_t n);\n\n// Prints uint8 variable with base and number of desired digits.\nvoid print_unsigned_int8(uint8_t n, uint8_t base, uint8_t digits); \n\n// Prints an uint8 variable in base 2.\nvoid print_uint8_base2(uint8_t n);\n\n// Prints an uint8 variable in base 10.\nvoid print_uint8_base10(uint8_t n);\n\nvoid printFloat(float n, uint8_t decimal_places);\n\n// Floating value printing handlers for special variables types used in Grbl. \n//  - CoordValue: Handles all position or coordinate values in inches or mm reporting.\n//  - RateValue: Handles feed rate and current velocity in inches or mm reporting.\n//  - SettingValue: Handles all floating point settings values (always in mm.)\nvoid printFloat_CoordValue(float n);\n\nvoid printFloat_RateValue(float n);\n\nvoid printFloat_SettingValue(float n);\n\n// Debug tool to print free memory in bytes at the called point. Not used otherwise.\nvoid printFreeMemory();\n\n#endif"
  },
  {
    "path": "probe.c",
    "content": "/*\n  probe.c - code pertaining to probing methods\n  Part of Grbl\n\n  Copyright (c) 2014-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n  \n#include \"grbl.h\"\n\n\n// Inverts the probe pin state depending on user settings and probing cycle mode.\nuint8_t probe_invert_mask;\n\n\n// Probe pin initialization routine.\nvoid probe_init() \n{\n  PROBE_DDR &= ~(PROBE_MASK); // Configure as input pins\n  #ifdef DISABLE_PROBE_PIN_PULL_UP\n    PROBE_PORT &= ~(PROBE_MASK); // Normal low operation. Requires external pull-down.\n  #else\n    PROBE_PORT |= PROBE_MASK;    // Enable internal pull-up resistors. Normal high operation.\n  #endif\n  // probe_configure_invert_mask(false); // Initialize invert mask. Not required. Updated when in-use.\n}\n\n\n// Called by probe_init() and the mc_probe() routines. Sets up the probe pin invert mask to \n// appropriately set the pin logic according to setting for normal-high/normal-low operation \n// and the probing cycle modes for toward-workpiece/away-from-workpiece. \nvoid probe_configure_invert_mask(uint8_t is_probe_away)\n{\n  probe_invert_mask = 0; // Initialize as zero.\n  if (bit_isfalse(settings.flags,BITFLAG_INVERT_PROBE_PIN)) { probe_invert_mask ^= PROBE_MASK; }\n  if (is_probe_away) { probe_invert_mask ^= PROBE_MASK; }\n}\n\n\n// Returns the probe pin state. Triggered = true. Called by gcode parser and probe state monitor.\nuint8_t probe_get_state() { return((PROBE_PIN & PROBE_MASK) ^ probe_invert_mask); }\n\n\n// Monitors probe pin state and records the system position when detected. Called by the\n// stepper ISR per ISR tick.\n// NOTE: This function must be extremely efficient as to not bog down the stepper ISR.\nvoid probe_state_monitor()\n{\n  if (sys.probe_state == PROBE_ACTIVE) {\n    if (probe_get_state()) {\n      sys.probe_state = PROBE_OFF;\n      memcpy(sys.probe_position, sys.position, sizeof(float)*N_AXIS);\n      bit_true(sys.rt_exec_state, EXEC_MOTION_CANCEL);\n    }\n  }\n}\n"
  },
  {
    "path": "probe.h",
    "content": "/*\n  probe.h - code pertaining to probing methods\n  Part of Grbl\n\n  Copyright (c) 2014-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n  \n#ifndef probe_h\n#define probe_h \n\n// Values that define the probing state machine.  \n#define PROBE_OFF     0 // Probing disabled or not in use. (Must be zero.)\n#define PROBE_ACTIVE  1 // Actively watching the input pin.\n\n// Probe pin initialization routine.\nvoid probe_init();\n\n// Called by probe_init() and the mc_probe() routines. Sets up the probe pin invert mask to \n// appropriately set the pin logic according to setting for normal-high/normal-low operation \n// and the probing cycle modes for toward-workpiece/away-from-workpiece. \nvoid probe_configure_invert_mask(uint8_t is_probe_away);\n\n// Returns probe pin state. Triggered = true. Called by gcode parser and probe state monitor.\nuint8_t probe_get_state();\n\n// Monitors probe pin state and records the system position when detected. Called by the\n// stepper ISR per ISR tick.\nvoid probe_state_monitor();\n\n#endif\n"
  },
  {
    "path": "protocol.c",
    "content": "/*\n  protocol.c - controls Grbl execution protocol and procedures\n  Part of Grbl\n  \n  Copyright (c) 2011-2015 Sungeun K. Jeon  \n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"grbl.h\"\n\n// Define different comment types for pre-parsing.\n#define COMMENT_NONE 0\n#define COMMENT_TYPE_PARENTHESES 1\n#define COMMENT_TYPE_SEMICOLON 2\n\n\nstatic char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated.\n\n\n// Directs and executes one line of formatted input from protocol_process. While mostly\n// incoming streaming g-code blocks, this also directs and executes Grbl internal commands,\n// such as settings, initiating the homing cycle, and toggling switch states.\nstatic void protocol_execute_line(char *line) \n{      \n  protocol_execute_realtime(); // Runtime command check point.\n  if (sys.abort) { return; } // Bail to calling function upon system abort  \n\n  #ifdef REPORT_ECHO_LINE_RECEIVED\n    report_echo_line_received(line);\n  #endif\n\n  if (line[0] == 0) {\n    // Empty or comment line. Send status message for syncing purposes.\n    report_status_message(STATUS_OK);\n\n  } else if (line[0] == '$') {\n    // Grbl '$' system command\n    report_status_message(system_execute_line(line));\n    \n  } else if (sys.state == STATE_ALARM) {\n    // Everything else is gcode. Block if in alarm mode.\n    report_status_message(STATUS_ALARM_LOCK);\n\n  } else {\n    // Parse and execute g-code block!\n    report_status_message(gc_execute_line(line));\n  }\n}\n\n\n/* \n  GRBL PRIMARY LOOP:\n*/\nvoid protocol_main_loop()\n{\n  // ------------------------------------------------------------\n  // Complete initialization procedures upon a power-up or reset.\n  // ------------------------------------------------------------\n  \n  // Print welcome message   \n  report_init_message();\n\n  // Check for and report alarm state after a reset, error, or an initial power up.\n  if (sys.state == STATE_ALARM) {\n    report_feedback_message(MESSAGE_ALARM_LOCK); \n  } else {\n    // All systems go! But first check for safety door.\n    if (system_check_safety_door_ajar()) {\n      bit_true(sys.rt_exec_state, EXEC_SAFETY_DOOR);\n      protocol_execute_realtime(); // Enter safety door mode. Should return as IDLE state.\n    } else {\n      sys.state = STATE_IDLE; // Set system to ready. Clear all state flags.\n    } \n    system_execute_startup(line); // Execute startup script.\n  }\n    \n  // ---------------------------------------------------------------------------------  \n  // Primary loop! Upon a system abort, this exits back to main() to reset the system. \n  // ---------------------------------------------------------------------------------  \n  \n  uint8_t comment = COMMENT_NONE;\n  uint8_t char_counter = 0;\n  uint8_t c;\n  for (;;) {\n\n    // Process one line of incoming serial data, as the data becomes available. Performs an\n    // initial filtering by removing spaces and comments and capitalizing all letters.\n    \n    // NOTE: While comment, spaces, and block delete(if supported) handling should technically \n    // be done in the g-code parser, doing it here helps compress the incoming data into Grbl's\n    // line buffer, which is limited in size. The g-code standard actually states a line can't\n    // exceed 256 characters, but the Arduino Uno does not have the memory space for this.\n    // With a better processor, it would be very easy to pull this initial parsing out as a \n    // seperate task to be shared by the g-code parser and Grbl's system commands.\n    \n    while((c = serial_read()) != SERIAL_NO_DATA) {\n      if ((c == '\\n') || (c == '\\r')) { // End of line reached\n        line[char_counter] = 0; // Set string termination character.\n        protocol_execute_line(line); // Line is complete. Execute it!\n        comment = COMMENT_NONE;\n        char_counter = 0;\n      } else {\n        if (comment != COMMENT_NONE) {\n          // Throw away all comment characters\n          if (c == ')') {\n            // End of comment. Resume line. But, not if semicolon type comment.\n            if (comment == COMMENT_TYPE_PARENTHESES) { comment = COMMENT_NONE; }\n          }\n        } else {\n          if (c <= ' ') { \n            // Throw away whitepace and control characters  \n          } else if (c == '/') { \n            // Block delete NOT SUPPORTED. Ignore character.\n            // NOTE: If supported, would simply need to check the system if block delete is enabled.\n          } else if (c == '(') {\n            // Enable comments flag and ignore all characters until ')' or EOL.\n            // NOTE: This doesn't follow the NIST definition exactly, but is good enough for now.\n            // In the future, we could simply remove the items within the comments, but retain the\n            // comment control characters, so that the g-code parser can error-check it.\n            comment = COMMENT_TYPE_PARENTHESES;\n          } else if (c == ';') {\n            // NOTE: ';' comment to EOL is a LinuxCNC definition. Not NIST.\n            comment = COMMENT_TYPE_SEMICOLON;\n            \n          // TODO: Install '%' feature \n          // } else if (c == '%') {\n            // Program start-end percent sign NOT SUPPORTED.\n            // NOTE: This maybe installed to tell Grbl when a program is running vs manual input,\n            // where, during a program, the system auto-cycle start will continue to execute \n            // everything until the next '%' sign. This will help fix resuming issues with certain\n            // functions that empty the planner buffer to execute its task on-time.\n\n          } else if (char_counter >= (LINE_BUFFER_SIZE-1)) {\n            // Detect line buffer overflow. Report error and reset line buffer.\n            report_status_message(STATUS_OVERFLOW);\n            comment = COMMENT_NONE;\n            char_counter = 0;\n          } else if (c >= 'a' && c <= 'z') { // Upcase lowercase\n            line[char_counter++] = c-'a'+'A';\n          } else {\n            line[char_counter++] = c;\n          }\n        }\n      }\n    }\n    \n    // If there are no more characters in the serial read buffer to be processed and executed,\n    // this indicates that g-code streaming has either filled the planner buffer or has \n    // completed. In either case, auto-cycle start, if enabled, any queued moves.\n    protocol_auto_cycle_start();\n\n    protocol_execute_realtime();  // Runtime command check point.\n    if (sys.abort) { return; } // Bail to main() program loop to reset system.\n              \n  }\n  \n  return; /* Never reached */\n}\n\n\n// Executes run-time commands, when required. This is called from various check points in the main\n// program, primarily where there may be a while loop waiting for a buffer to clear space or any\n// point where the execution time from the last check point may be more than a fraction of a second.\n// This is a way to execute realtime commands asynchronously (aka multitasking) with grbl's g-code\n// parsing and planning functions. This function also serves as an interface for the interrupts to \n// set the system realtime flags, where only the main program handles them, removing the need to\n// define more computationally-expensive volatile variables. This also provides a controlled way to \n// execute certain tasks without having two or more instances of the same task, such as the planner\n// recalculating the buffer upon a feedhold or override.\n// NOTE: The sys.rt_exec_state variable flags are set by any process, step or serial interrupts, pinouts,\n// limit switches, or the main program.\nvoid protocol_execute_realtime()\n{\n  uint8_t rt_exec; // Temp variable to avoid calling volatile multiple times.\n\n  do { // If system is suspended, suspend loop restarts here.\n    \n  // Check and execute alarms. \n  rt_exec = sys.rt_exec_alarm; // Copy volatile sys.rt_exec_alarm.\n  if (rt_exec) { // Enter only if any bit flag is true\n    // System alarm. Everything has shutdown by something that has gone severely wrong. Report\n    // the source of the error to the user. If critical, Grbl disables by entering an infinite\n    // loop until system reset/abort.\n    sys.state = STATE_ALARM; // Set system alarm state\n    if (rt_exec & EXEC_ALARM_HARD_LIMIT) {\n      report_alarm_message(ALARM_HARD_LIMIT_ERROR); \n    } else if (rt_exec & EXEC_ALARM_SOFT_LIMIT) {\n      report_alarm_message(ALARM_SOFT_LIMIT_ERROR);\n    } else if (rt_exec & EXEC_ALARM_ABORT_CYCLE) {      \n      report_alarm_message(ALARM_ABORT_CYCLE);\n    } else if (rt_exec & EXEC_ALARM_PROBE_FAIL) {\n      report_alarm_message(ALARM_PROBE_FAIL);\n    } else if (rt_exec & EXEC_ALARM_HOMING_FAIL) {\n      report_alarm_message(ALARM_HOMING_FAIL);\n    }\n    // Halt everything upon a critical event flag. Currently hard and soft limits flag this.\n    if (rt_exec & EXEC_CRITICAL_EVENT) {\n      report_feedback_message(MESSAGE_CRITICAL_EVENT);\n      bit_false_atomic(sys.rt_exec_state,EXEC_RESET); // Disable any existing reset\n      do { \n        // Nothing. Block EVERYTHING until user issues reset or power cycles. Hard limits\n        // typically occur while unattended or not paying attention. Gives the user time\n        // to do what is needed before resetting, like killing the incoming stream. The \n        // same could be said about soft limits. While the position is not lost, the incoming\n        // stream could be still engaged and cause a serious crash if it continues afterwards.\n        \n        // TODO: Allow status reports during a critical alarm. Still need to think about implications of this.\n//         if (sys.rt_exec_state & EXEC_STATUS_REPORT) { \n//           report_realtime_status();\n//           bit_false_atomic(sys.rt_exec_state,EXEC_STATUS_REPORT); \n//         }\n      } while (bit_isfalse(sys.rt_exec_state,EXEC_RESET));\n    }\n    bit_false_atomic(sys.rt_exec_alarm,0xFF); // Clear all alarm flags\n  }\n  \n  // Check amd execute realtime commands\n  rt_exec = sys.rt_exec_state; // Copy volatile sys.rt_exec_state.\n  if (rt_exec) { // Enter only if any bit flag is true\n  \n    // Execute system abort. \n    if (rt_exec & EXEC_RESET) {\n      sys.abort = true;  // Only place this is set true.\n      return; // Nothing else to do but exit.\n    }\n    \n    // Execute and serial print status\n    if (rt_exec & EXEC_STATUS_REPORT) { \n      report_realtime_status();\n      bit_false_atomic(sys.rt_exec_state,EXEC_STATUS_REPORT);\n    }\n  \n    // Execute hold states.\n    // NOTE: The math involved to calculate the hold should be low enough for most, if not all, \n    // operational scenarios. Once hold is initiated, the system enters a suspend state to block\n    // all main program processes until either reset or resumed.\n    if (rt_exec & (EXEC_MOTION_CANCEL | EXEC_FEED_HOLD | EXEC_SAFETY_DOOR)) {\n      \n      // TODO: CHECK MODE? How to handle this? Likely nothing, since it only works when IDLE and then resets Grbl.\n                \n      // State check for allowable states for hold methods.\n      if ((sys.state == STATE_IDLE) || (sys.state & (STATE_CYCLE | STATE_HOMING | STATE_MOTION_CANCEL | STATE_HOLD | STATE_SAFETY_DOOR))) {\n\n        // If in CYCLE state, all hold states immediately initiate a motion HOLD.\n        if (sys.state == STATE_CYCLE) {\n          st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration.\n          sys.suspend = SUSPEND_ENABLE_HOLD; // Initiate holding cycle with flag.\n        }\n        // If IDLE, Grbl is not in motion. Simply indicate suspend ready state.\n        if (sys.state == STATE_IDLE) { sys.suspend = SUSPEND_ENABLE_READY; }\n        \n        // Execute and flag a motion cancel with deceleration and return to idle. Used primarily by probing cycle\n        // to halt and cancel the remainder of the motion.\n        if (rt_exec & EXEC_MOTION_CANCEL) {\n          // MOTION_CANCEL only occurs during a CYCLE, but a HOLD and SAFETY_DOOR may been initiated beforehand\n          // to hold the CYCLE. If so, only flag that motion cancel is complete.\n          if (sys.state == STATE_CYCLE) { sys.state = STATE_MOTION_CANCEL; }\n          sys.suspend |= SUSPEND_MOTION_CANCEL; // Indicate motion cancel when resuming. Special motion complete.\n        }\n    \n        // Execute a feed hold with deceleration, only during cycle.\n        if (rt_exec & EXEC_FEED_HOLD) {\n          // Block SAFETY_DOOR state from prematurely changing back to HOLD.\n          if (bit_isfalse(sys.state,STATE_SAFETY_DOOR)) { sys.state = STATE_HOLD; }\n        }\n  \n        // Execute a safety door stop with a feed hold, only during a cycle, and disable spindle/coolant.\n        // NOTE: Safety door differs from feed holds by stopping everything no matter state, disables powered\n        // devices (spindle/coolant), and blocks resuming until switch is re-engaged. The power-down is \n        // executed here, if IDLE, or when the CYCLE completes via the EXEC_CYCLE_STOP flag.\n        if (rt_exec & EXEC_SAFETY_DOOR) {\n          report_feedback_message(MESSAGE_SAFETY_DOOR_AJAR); \n          // If already in active, ready-to-resume HOLD, set CYCLE_STOP flag to force de-energize.\n          // NOTE: Only temporarily sets the 'rt_exec' variable, not the volatile 'rt_exec_state' variable.\n          if (sys.suspend & SUSPEND_ENABLE_READY) { bit_true(rt_exec,EXEC_CYCLE_STOP); }\n          sys.suspend |= SUSPEND_ENERGIZE;\n          sys.state = STATE_SAFETY_DOOR;\n        }\n         \n      }\n      bit_false_atomic(sys.rt_exec_state,(EXEC_MOTION_CANCEL | EXEC_FEED_HOLD | EXEC_SAFETY_DOOR));      \n    }\n          \n    // Execute a cycle start by starting the stepper interrupt to begin executing the blocks in queue.\n    if (rt_exec & EXEC_CYCLE_START) {\n      // Block if called at same time as the hold commands: feed hold, motion cancel, and safety door.\n      // Ensures auto-cycle-start doesn't resume a hold without an explicit user-input.\n      if (!(rt_exec & (EXEC_FEED_HOLD | EXEC_MOTION_CANCEL | EXEC_SAFETY_DOOR))) { \n        // Cycle start only when IDLE or when a hold is complete and ready to resume.\n        // NOTE: SAFETY_DOOR is implicitly blocked. It reverts to HOLD when the door is closed.\n        if ((sys.state == STATE_IDLE) || ((sys.state & (STATE_HOLD | STATE_MOTION_CANCEL)) && (sys.suspend & SUSPEND_ENABLE_READY))) {\n          // Re-energize powered components, if disabled by SAFETY_DOOR.\n          if (sys.suspend & SUSPEND_ENERGIZE) { \n            // Delayed Tasks: Restart spindle and coolant, delay to power-up, then resume cycle.\n            if (gc_state.modal.spindle != SPINDLE_DISABLE) { \n              spindle_set_state(gc_state.modal.spindle, gc_state.spindle_speed); \n              delay_ms(SAFETY_DOOR_SPINDLE_DELAY); // TODO: Blocking function call. Need a non-blocking one eventually.\n            }\n            if (gc_state.modal.coolant != COOLANT_DISABLE) { \n              coolant_set_state(gc_state.modal.coolant); \n              delay_ms(SAFETY_DOOR_COOLANT_DELAY); // TODO: Blocking function call. Need a non-blocking one eventually.\n            }\n            // TODO: Install return to pre-park position.\n          }\n          // Start cycle only if queued motions exist in planner buffer and the motion is not canceled.\n          if (plan_get_current_block() && bit_isfalse(sys.suspend,SUSPEND_MOTION_CANCEL)) {\n            sys.state = STATE_CYCLE;\n            st_prep_buffer(); // Initialize step segment buffer before beginning cycle.\n            st_wake_up();\n          } else { // Otherwise, do nothing. Set and resume IDLE state.\n            sys.state = STATE_IDLE;\n          }\n          sys.suspend = SUSPEND_DISABLE; // Break suspend state.\n        }\n      }    \n      bit_false_atomic(sys.rt_exec_state,EXEC_CYCLE_START);\n    }\n    \n    // Reinitializes the cycle plan and stepper system after a feed hold for a resume. Called by \n    // realtime command execution in the main program, ensuring that the planner re-plans safely.\n    // NOTE: Bresenham algorithm variables are still maintained through both the planner and stepper\n    // cycle reinitializations. The stepper path should continue exactly as if nothing has happened.   \n    // NOTE: EXEC_CYCLE_STOP is set by the stepper subsystem when a cycle or feed hold completes.\n    if (rt_exec & EXEC_CYCLE_STOP) {\n      if (sys.state & (STATE_HOLD | STATE_SAFETY_DOOR)) {\n        // Hold complete. Set to indicate ready to resume.  Remain in HOLD or DOOR states until user\n        // has issued a resume command or reset.\n        if (sys.suspend & SUSPEND_ENERGIZE) { // De-energize system if safety door has been opened.\n          spindle_stop();\n          coolant_stop();\n          // TODO: Install parking motion here.\n        }\n        bit_true(sys.suspend,SUSPEND_ENABLE_READY);\n      } else { // Motion is complete. Includes CYCLE, HOMING, and MOTION_CANCEL states.\n        sys.suspend = SUSPEND_DISABLE;\n        sys.state = STATE_IDLE;\n      }\n      bit_false_atomic(sys.rt_exec_state,EXEC_CYCLE_STOP);\n    }\n    \n  }\n\n  // Overrides flag byte (sys.override) and execution should be installed here, since they \n  // are realtime and require a direct and controlled interface to the main stepper program.\n\n  // Reload step segment buffer\n  if (sys.state & (STATE_CYCLE | STATE_HOLD | STATE_MOTION_CANCEL | STATE_SAFETY_DOOR | STATE_HOMING)) { st_prep_buffer(); }  \n  \n  // If safety door was opened, actively check when safety door is closed and ready to resume.\n  // NOTE: This unlocks the SAFETY_DOOR state to a HOLD state, such that CYCLE_START can activate a resume.\n  if (sys.state == STATE_SAFETY_DOOR) { \n    if (bit_istrue(sys.suspend,SUSPEND_ENABLE_READY)) { \n      if (!(system_check_safety_door_ajar())) {\n        sys.state = STATE_HOLD; // Update to HOLD state to indicate door is closed and ready to resume.\n      }\n    }\n  }\n\n  } while(sys.suspend); // Check for system suspend state before exiting.\n  \n}  \n\n\n// Block until all buffered steps are executed or in a cycle state. Works with feed hold\n// during a synchronize call, if it should happen. Also, waits for clean cycle end.\nvoid protocol_buffer_synchronize()\n{\n  // If system is queued, ensure cycle resumes if the auto start flag is present.\n  protocol_auto_cycle_start();\n  do {\n    protocol_execute_realtime();   // Check and execute run-time commands\n    if (sys.abort) { return; } // Check for system abort\n  } while (plan_get_current_block() || (sys.state == STATE_CYCLE));\n}\n\n\n// Auto-cycle start has two purposes: 1. Resumes a plan_synchronize() call from a function that\n// requires the planner buffer to empty (spindle enable, dwell, etc.) 2. As a user setting that \n// automatically begins the cycle when a user enters a valid motion command manually. This is \n// intended as a beginners feature to help new users to understand g-code. It can be disabled\n// as a beginner tool, but (1.) still operates. If disabled, the operation of cycle start is\n// manually issuing a cycle start command whenever the user is ready and there is a valid motion \n// command in the planner queue.\n// NOTE: This function is called from the main loop, buffer sync, and mc_line() only and executes \n// when one of these conditions exist respectively: There are no more blocks sent (i.e. streaming \n// is finished, single commands), a command that needs to wait for the motions in the buffer to \n// execute calls a buffer sync, or the planner buffer is full and ready to go.\nvoid protocol_auto_cycle_start() { bit_true_atomic(sys.rt_exec_state, EXEC_CYCLE_START); } \n"
  },
  {
    "path": "protocol.h",
    "content": "/*\n  protocol.h - controls Grbl execution protocol and procedures\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef protocol_h\n#define protocol_h\n\n// Line buffer size from the serial input stream to be executed.\n// NOTE: Not a problem except for extreme cases, but the line buffer size can be too small\n// and g-code blocks can get truncated. Officially, the g-code standards support up to 256\n// characters. In future versions, this will be increased, when we know how much extra\n// memory space we can invest into here or we re-write the g-code parser not to have this \n// buffer.\n#ifndef LINE_BUFFER_SIZE\n  #define LINE_BUFFER_SIZE 80\n#endif\n\n// Starts Grbl main loop. It handles all incoming characters from the serial port and executes\n// them as they complete. It is also responsible for finishing the initialization procedures.\nvoid protocol_main_loop();\n\n// Checks and executes a realtime command at various stop points in main program\nvoid protocol_execute_realtime();\n\n// Notify the stepper subsystem to start executing the g-code program in buffer.\n// void protocol_cycle_start();\n\n// Reinitializes the buffer after a feed hold for a resume.\n// void protocol_cycle_reinitialize(); \n\n// Initiates a feed hold of the running program\n// void protocol_feed_hold();\n\n// Executes the auto cycle feature, if enabled.\nvoid protocol_auto_cycle_start();\n\n// Block until all buffered steps are executed\nvoid protocol_buffer_synchronize();\n\n#endif\n"
  },
  {
    "path": "report.c",
    "content": "/*\n  report.c - reporting and messaging methods\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon  \n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n/* \n  This file functions as the primary feedback interface for Grbl. Any outgoing data, such \n  as the protocol status messages, feedback messages, and status reports, are stored here.\n  For the most part, these functions primarily are called from protocol.c methods. If a \n  different style feedback is desired (i.e. JSON), then a user can change these following \n  methods to accomodate their needs.\n*/\n\n#include \"grbl.h\"\n\n\n// Handles the primary confirmation protocol response for streaming interfaces and human-feedback.\n// For every incoming line, this method responds with an 'ok' for a successful command or an \n// 'error:'  to indicate some error event with the line or some critical system error during \n// operation. Errors events can originate from the g-code parser, settings module, or asynchronously\n// from a critical error, such as a triggered hard limit. Interface should always monitor for these\n// responses.\n// NOTE: In silent mode, all error codes are greater than zero.\n// TODO: Install silent mode to return only numeric values, primarily for GUIs.\nvoid report_status_message(uint8_t status_code) \n{\n  if (status_code == 0) { // STATUS_OK\n    printPgmString(PSTR(\"ok\\r\\n\"));\n  } else {\n    printPgmString(PSTR(\"error: \"));\n    #ifdef REPORT_GUI_MODE\n      print_uint8_base10(status_code);\n    #else\n      switch(status_code) {          \n        case STATUS_EXPECTED_COMMAND_LETTER:\n        printPgmString(PSTR(\"Expected command letter\")); break;\n        case STATUS_BAD_NUMBER_FORMAT:\n        printPgmString(PSTR(\"Bad number format\")); break;\n        case STATUS_INVALID_STATEMENT:\n        printPgmString(PSTR(\"Invalid statement\")); break;\n        case STATUS_NEGATIVE_VALUE:\n        printPgmString(PSTR(\"Value < 0\")); break;\n        case STATUS_SETTING_DISABLED:\n        printPgmString(PSTR(\"Setting disabled\")); break;\n        case STATUS_SETTING_STEP_PULSE_MIN:\n        printPgmString(PSTR(\"Value < 3 usec\")); break;\n        case STATUS_SETTING_READ_FAIL:\n        printPgmString(PSTR(\"EEPROM read fail. Using defaults\")); break;\n        case STATUS_IDLE_ERROR:\n        printPgmString(PSTR(\"Not idle\")); break;\n        case STATUS_ALARM_LOCK:\n        printPgmString(PSTR(\"Alarm lock\")); break;\n        case STATUS_SOFT_LIMIT_ERROR:\n        printPgmString(PSTR(\"Homing not enabled\")); break;\n        case STATUS_OVERFLOW:\n        printPgmString(PSTR(\"Line overflow\")); break;\n        #ifdef MAX_STEP_RATE_HZ\n          case STATUS_MAX_STEP_RATE_EXCEEDED: \n          printPgmString(PSTR(\"Step rate > 30kHz\")); break;\n        #endif      \n        // Common g-code parser errors.\n        case STATUS_GCODE_MODAL_GROUP_VIOLATION:\n        printPgmString(PSTR(\"Modal group violation\")); break;\n        case STATUS_GCODE_UNSUPPORTED_COMMAND:\n        printPgmString(PSTR(\"Unsupported command\")); break;\n        case STATUS_GCODE_UNDEFINED_FEED_RATE:\n        printPgmString(PSTR(\"Undefined feed rate\")); break;\n        default:\n          // Remaining g-code parser errors with error codes\n          printPgmString(PSTR(\"Invalid gcode ID:\"));\n          print_uint8_base10(status_code); // Print error code for user reference\n      }\n    #endif  \n    printPgmString(PSTR(\"\\r\\n\"));\n  }\n}\n\n// Prints alarm messages.\nvoid report_alarm_message(int8_t alarm_code)\n{\n  printPgmString(PSTR(\"ALARM: \"));\n  #ifdef REPORT_GUI_MODE\n    print_uint8_base10(alarm_code);\n  #else\n    switch (alarm_code) {\n      case ALARM_HARD_LIMIT_ERROR: \n      printPgmString(PSTR(\"Hard limit\")); break;\n      case ALARM_SOFT_LIMIT_ERROR:\n      printPgmString(PSTR(\"Soft limit\")); break;\n      case ALARM_ABORT_CYCLE: \n      printPgmString(PSTR(\"Abort during cycle\")); break;\n      case ALARM_PROBE_FAIL:\n      printPgmString(PSTR(\"Probe fail\")); break;\n      case ALARM_HOMING_FAIL:\n      printPgmString(PSTR(\"Homing fail\")); break;\n    }\n  #endif\n  printPgmString(PSTR(\"\\r\\n\"));\n  delay_ms(500); // Force delay to ensure message clears serial write buffer.\n}\n\n// Prints feedback messages. This serves as a centralized method to provide additional\n// user feedback for things that are not of the status/alarm message protocol. These are\n// messages such as setup warnings, switch toggling, and how to exit alarms.\n// NOTE: For interfaces, messages are always placed within brackets. And if silent mode\n// is installed, the message number codes are less than zero.\n// TODO: Install silence feedback messages option in settings\nvoid report_feedback_message(uint8_t message_code)\n{\n  printPgmString(PSTR(\"[\"));\n  switch(message_code) {\n    case MESSAGE_CRITICAL_EVENT:\n    printPgmString(PSTR(\"Reset to continue\")); break;\n    case MESSAGE_ALARM_LOCK:\n    printPgmString(PSTR(\"'$H'|'$X' to unlock\")); break;\n    case MESSAGE_ALARM_UNLOCK:\n    printPgmString(PSTR(\"Caution: Unlocked\")); break;\n    case MESSAGE_ENABLED:\n    printPgmString(PSTR(\"Enabled\")); break;\n    case MESSAGE_DISABLED:\n    printPgmString(PSTR(\"Disabled\")); break; \n    case MESSAGE_SAFETY_DOOR_AJAR:\n    printPgmString(PSTR(\"Check Door\")); break;\n    case MESSAGE_PROGRAM_END:\n    printPgmString(PSTR(\"Pgm End\")); break;\n    case MESSAGE_RESTORE_DEFAULTS:\n    printPgmString(PSTR(\"Restoring defaults\")); break;\n  }\n  printPgmString(PSTR(\"]\\r\\n\"));\n}\n\n\n// Welcome message\nvoid report_init_message()\n{\n  printPgmString(PSTR(\"\\r\\nGrbl \" GRBL_VERSION \" ['$' for help]\\r\\n\"));\n}\n\n// Grbl help message\nvoid report_grbl_help() {\n  #ifndef REPORT_GUI_MODE\n    printPgmString(PSTR(\"$$ (view Grbl settings)\\r\\n\"\n                        \"$# (view # parameters)\\r\\n\"\n                        \"$G (view parser state)\\r\\n\"\n                        \"$I (view build info)\\r\\n\"\n                        \"$N (view startup blocks)\\r\\n\"\n                        \"$x=value (save Grbl setting)\\r\\n\"\n                        \"$Nx=line (save startup block)\\r\\n\"\n                        \"$C (check gcode mode)\\r\\n\"\n                        \"$X (kill alarm lock)\\r\\n\"\n                        \"$H (run homing cycle)\\r\\n\"\n                        \"~ (cycle start)\\r\\n\"\n                        \"! (feed hold)\\r\\n\"\n                        \"? (current status)\\r\\n\"\n                        \"ctrl-x (reset Grbl)\\r\\n\"));\n  #endif\n}\n\n\n// Grbl global settings print out.\n// NOTE: The numbering scheme here must correlate to storing in settings.c\nvoid report_grbl_settings() {\n  // Print Grbl settings.\n  #ifdef REPORT_GUI_MODE\n    printPgmString(PSTR(\"$0=\")); print_uint8_base10(settings.pulse_microseconds);\n    printPgmString(PSTR(\"\\r\\n$1=\")); print_uint8_base10(settings.stepper_idle_lock_time);\n    printPgmString(PSTR(\"\\r\\n$2=\")); print_uint8_base10(settings.step_invert_mask); \n    printPgmString(PSTR(\"\\r\\n$3=\")); print_uint8_base10(settings.dir_invert_mask); \n    printPgmString(PSTR(\"\\r\\n$4=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE));\n    printPgmString(PSTR(\"\\r\\n$5=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS));\n    printPgmString(PSTR(\"\\r\\n$6=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_PROBE_PIN));\n    printPgmString(PSTR(\"\\r\\n$10=\")); print_uint8_base10(settings.status_report_mask);\n    printPgmString(PSTR(\"\\r\\n$11=\")); printFloat_SettingValue(settings.junction_deviation);\n    printPgmString(PSTR(\"\\r\\n$12=\")); printFloat_SettingValue(settings.arc_tolerance);\n    printPgmString(PSTR(\"\\r\\n$13=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));\n    printPgmString(PSTR(\"\\r\\n$20=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE));\n    printPgmString(PSTR(\"\\r\\n$21=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));\n    printPgmString(PSTR(\"\\r\\n$22=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));\n    printPgmString(PSTR(\"\\r\\n$23=\")); print_uint8_base10(settings.homing_dir_mask);\n    printPgmString(PSTR(\"\\r\\n$24=\")); printFloat_SettingValue(settings.homing_feed_rate);\n    printPgmString(PSTR(\"\\r\\n$25=\")); printFloat_SettingValue(settings.homing_seek_rate);\n    printPgmString(PSTR(\"\\r\\n$26=\")); print_uint8_base10(settings.homing_debounce_delay);\n    printPgmString(PSTR(\"\\r\\n$27=\")); printFloat_SettingValue(settings.homing_pulloff);\n    printPgmString(PSTR(\"\\r\\n\"));\n  #else      \n    printPgmString(PSTR(\"$0=\")); print_uint8_base10(settings.pulse_microseconds);\n    printPgmString(PSTR(\" (step pulse, usec)\\r\\n$1=\")); print_uint8_base10(settings.stepper_idle_lock_time);\n    printPgmString(PSTR(\" (step idle delay, msec)\\r\\n$2=\")); print_uint8_base10(settings.step_invert_mask); \n    printPgmString(PSTR(\" (step port invert mask:\")); print_uint8_base2(settings.step_invert_mask);  \n    printPgmString(PSTR(\")\\r\\n$3=\")); print_uint8_base10(settings.dir_invert_mask); \n    printPgmString(PSTR(\" (dir port invert mask:\")); print_uint8_base2(settings.dir_invert_mask);  \n    printPgmString(PSTR(\")\\r\\n$4=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE));\n    printPgmString(PSTR(\" (step enable invert, bool)\\r\\n$5=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS));\n    printPgmString(PSTR(\" (limit pins invert, bool)\\r\\n$6=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_PROBE_PIN));\n    printPgmString(PSTR(\" (probe pin invert, bool)\\r\\n$10=\")); print_uint8_base10(settings.status_report_mask);\n    printPgmString(PSTR(\" (status report mask:\")); print_uint8_base2(settings.status_report_mask);\n    printPgmString(PSTR(\")\\r\\n$11=\")); printFloat_SettingValue(settings.junction_deviation);\n    printPgmString(PSTR(\" (junction deviation, mm)\\r\\n$12=\")); printFloat_SettingValue(settings.arc_tolerance);\n    printPgmString(PSTR(\" (arc tolerance, mm)\\r\\n$13=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));\n    printPgmString(PSTR(\" (report inches, bool)\\r\\n$20=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE));\n    printPgmString(PSTR(\" (soft limits, bool)\\r\\n$21=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));\n    printPgmString(PSTR(\" (hard limits, bool)\\r\\n$22=\")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));\n    printPgmString(PSTR(\" (homing cycle, bool)\\r\\n$23=\")); print_uint8_base10(settings.homing_dir_mask);\n    printPgmString(PSTR(\" (homing dir invert mask:\")); print_uint8_base2(settings.homing_dir_mask);  \n    printPgmString(PSTR(\")\\r\\n$24=\")); printFloat_SettingValue(settings.homing_feed_rate);\n    printPgmString(PSTR(\" (homing feed, mm/min)\\r\\n$25=\")); printFloat_SettingValue(settings.homing_seek_rate);\n    printPgmString(PSTR(\" (homing seek, mm/min)\\r\\n$26=\")); print_uint8_base10(settings.homing_debounce_delay);\n    printPgmString(PSTR(\" (homing debounce, msec)\\r\\n$27=\")); printFloat_SettingValue(settings.homing_pulloff);\n    printPgmString(PSTR(\" (homing pull-off, mm)\\r\\n\"));\n  #endif\n  \n  // Print axis settings\n  uint8_t idx, set_idx;\n  uint8_t val = AXIS_SETTINGS_START_VAL;\n  for (set_idx=0; set_idx<AXIS_N_SETTINGS; set_idx++) {\n    for (idx=0; idx<N_AXIS; idx++) {\n      printPgmString(PSTR(\"$\"));\n      print_uint8_base10(val+idx);\n      printPgmString(PSTR(\"=\"));\n      switch (set_idx) {\n        case 0: printFloat_SettingValue(settings.steps_per_mm[idx]); break;\n        case 1: printFloat_SettingValue(settings.max_rate[idx]); break;\n        case 2: printFloat_SettingValue(settings.acceleration[idx]/(60*60)); break;\n        case 3: printFloat_SettingValue(-settings.max_travel[idx]); break;\n      }\n      #ifdef REPORT_GUI_MODE\n        printPgmString(PSTR(\"\\r\\n\"));\n      #else\n        printPgmString(PSTR(\" (\"));\n        switch (idx) {\n          case X_AXIS: printPgmString(PSTR(\"x\")); break;\n          case Y_AXIS: printPgmString(PSTR(\"y\")); break;\n          case Z_AXIS: printPgmString(PSTR(\"z\")); break;\n        }\n        switch (set_idx) {\n          case 0: printPgmString(PSTR(\", step/mm\")); break;\n          case 1: printPgmString(PSTR(\" max rate, mm/min\")); break;\n          case 2: printPgmString(PSTR(\" accel, mm/sec^2\")); break;\n          case 3: printPgmString(PSTR(\" max travel, mm\")); break;\n        }      \n        printPgmString(PSTR(\")\\r\\n\"));\n      #endif\n    }\n    val += AXIS_SETTINGS_INCREMENT;\n  }  \n}\n\n\n// Prints current probe parameters. Upon a probe command, these parameters are updated upon a\n// successful probe or upon a failed probe with the G38.3 without errors command (if supported). \n// These values are retained until Grbl is power-cycled, whereby they will be re-zeroed.\nvoid report_probe_parameters()\n{\n  uint8_t i;\n  float print_position[N_AXIS];\n \n  // Report in terms of machine position.\n  printPgmString(PSTR(\"[PRB:\"));\n  for (i=0; i< N_AXIS; i++) {\n    print_position[i] = system_convert_axis_steps_to_mpos(sys.probe_position,i);\n    printFloat_CoordValue(print_position[i]);\n    if (i < (N_AXIS-1)) { printPgmString(PSTR(\",\")); }\n  }\n  printPgmString(PSTR(\":\"));\n  print_uint8_base10(sys.probe_succeeded);\n  printPgmString(PSTR(\"]\\r\\n\"));\n}\n\n\n// Prints Grbl NGC parameters (coordinate offsets, probing)\nvoid report_ngc_parameters()\n{\n  float coord_data[N_AXIS];\n  uint8_t coord_select, i;\n  for (coord_select = 0; coord_select <= SETTING_INDEX_NCOORD; coord_select++) { \n    if (!(settings_read_coord_data(coord_select,coord_data))) { \n      report_status_message(STATUS_SETTING_READ_FAIL); \n      return;\n    } \n    printPgmString(PSTR(\"[G\"));\n    switch (coord_select) {\n      case 6: printPgmString(PSTR(\"28\")); break;\n      case 7: printPgmString(PSTR(\"30\")); break;\n      default: print_uint8_base10(coord_select+54); break; // G54-G59\n    }  \n    printPgmString(PSTR(\":\"));         \n    for (i=0; i<N_AXIS; i++) {\n      printFloat_CoordValue(coord_data[i]);\n      if (i < (N_AXIS-1)) { printPgmString(PSTR(\",\")); }\n      else { printPgmString(PSTR(\"]\\r\\n\")); }\n    } \n  }\n  printPgmString(PSTR(\"[G92:\")); // Print G92,G92.1 which are not persistent in memory\n  for (i=0; i<N_AXIS; i++) {\n    printFloat_CoordValue(gc_state.coord_offset[i]);\n    if (i < (N_AXIS-1)) { printPgmString(PSTR(\",\")); }\n    else { printPgmString(PSTR(\"]\\r\\n\")); }\n  } \n  printPgmString(PSTR(\"[TLO:\")); // Print tool length offset value\n  printFloat_CoordValue(gc_state.tool_length_offset);\n  printPgmString(PSTR(\"]\\r\\n\"));\n  report_probe_parameters(); // Print probe parameters. Not persistent in memory.\n}\n\n\n// Print current gcode parser mode state\nvoid report_gcode_modes()\n{\n  printPgmString(PSTR(\"[\"));\n  \n  switch (gc_state.modal.motion) {\n    case MOTION_MODE_SEEK : printPgmString(PSTR(\"G0\")); break;\n    case MOTION_MODE_LINEAR : printPgmString(PSTR(\"G1\")); break;\n    case MOTION_MODE_CW_ARC : printPgmString(PSTR(\"G2\")); break;\n    case MOTION_MODE_CCW_ARC : printPgmString(PSTR(\"G3\")); break;\n    case MOTION_MODE_NONE : printPgmString(PSTR(\"G80\")); break;\n    default: \n      printPgmString(PSTR(\"G38.\"));\n      print_uint8_base10(gc_state.modal.motion - (MOTION_MODE_PROBE_TOWARD+2));\n  }\n\n  printPgmString(PSTR(\" G\"));\n  print_uint8_base10(gc_state.modal.coord_select+54);\n  \n  switch (gc_state.modal.plane_select) {\n    case PLANE_SELECT_XY : printPgmString(PSTR(\" G17\")); break;\n    case PLANE_SELECT_ZX : printPgmString(PSTR(\" G18\")); break;\n    case PLANE_SELECT_YZ : printPgmString(PSTR(\" G19\")); break;\n  }\n  \n  if (gc_state.modal.units == UNITS_MODE_MM) { printPgmString(PSTR(\" G21\")); }\n  else { printPgmString(PSTR(\" G20\")); }\n  \n  if (gc_state.modal.distance == DISTANCE_MODE_ABSOLUTE) { printPgmString(PSTR(\" G90\")); }\n  else { printPgmString(PSTR(\" G91\")); }\n  \n  if (gc_state.modal.feed_rate == FEED_RATE_MODE_INVERSE_TIME) { printPgmString(PSTR(\" G93\")); }\n  else { printPgmString(PSTR(\" G94\")); }\n    \n  switch (gc_state.modal.program_flow) {\n    case PROGRAM_FLOW_RUNNING : printPgmString(PSTR(\" M0\")); break;\n    case PROGRAM_FLOW_PAUSED : printPgmString(PSTR(\" M1\")); break;\n    case PROGRAM_FLOW_COMPLETED : printPgmString(PSTR(\" M2\")); break;\n  }\n\n  switch (gc_state.modal.spindle) {\n    case SPINDLE_ENABLE_CW : printPgmString(PSTR(\" M3\")); break;\n    case SPINDLE_ENABLE_CCW : printPgmString(PSTR(\" M4\")); break;\n    case SPINDLE_DISABLE : printPgmString(PSTR(\" M5\")); break;\n  }\n  \n  switch (gc_state.modal.coolant) {\n    case COOLANT_DISABLE : printPgmString(PSTR(\" M9\")); break;\n    case COOLANT_FLOOD_ENABLE : printPgmString(PSTR(\" M8\")); break;\n    #ifdef ENABLE_M7\n      case COOLANT_MIST_ENABLE : printPgmString(PSTR(\" M7\")); break;\n    #endif\n  }\n  \n  printPgmString(PSTR(\" T\"));\n  print_uint8_base10(gc_state.tool);\n  \n  printPgmString(PSTR(\" F\"));\n  printFloat_RateValue(gc_state.feed_rate);\n  \n  #ifdef VARIABLE_SPINDLE\n    printPgmString(PSTR(\" S\"));\n    printFloat_RateValue(gc_state.spindle_speed);\n  #endif\n\n  printPgmString(PSTR(\"]\\r\\n\"));\n}\n\n// Prints specified startup line\nvoid report_startup_line(uint8_t n, char *line)\n{\n  printPgmString(PSTR(\"$N\")); print_uint8_base10(n);\n  printPgmString(PSTR(\"=\")); printString(line);\n  printPgmString(PSTR(\"\\r\\n\"));\n}\n\n\n// Prints build info line\nvoid report_build_info(char *line)\n{\n  printPgmString(PSTR(\"[\" GRBL_VERSION \".\" GRBL_VERSION_BUILD \":\"));\n  printString(line);\n  printPgmString(PSTR(\"]\\r\\n\"));\n}\n\n\n// Prints the character string line Grbl has received from the user, which has been pre-parsed,\n// and has been sent into protocol_execute_line() routine to be executed by Grbl.\nvoid report_echo_line_received(char *line)\n{\n  printPgmString(PSTR(\"[echo: \")); printString(line);\n  printPgmString(PSTR(\"]\\r\\n\"));\n}\n\n\n // Prints real-time data. This function grabs a real-time snapshot of the stepper subprogram \n // and the actual location of the CNC machine. Users may change the following function to their\n // specific needs, but the desired real-time data report must be as short as possible. This is\n // requires as it minimizes the computational overhead and allows grbl to keep running smoothly, \n // especially during g-code programs with fast, short line segments and high frequency reports (5-20Hz).\nvoid report_realtime_status()\n{\n  // **Under construction** Bare-bones status report. Provides real-time machine position relative to \n  // the system power on location (0,0,0) and work coordinate position (G54 and G92 applied). Eventually\n  // to be added are distance to go on block, processed block id, and feed rate. Also a settings bitmask\n  // for a user to select the desired real-time data.\n  uint8_t idx;\n  int32_t current_position[N_AXIS]; // Copy current state of the system position variable\n  memcpy(current_position,sys.position,sizeof(sys.position));\n  float print_position[N_AXIS];\n \n  // Report current machine state\n  switch (sys.state) {\n    case STATE_IDLE: printPgmString(PSTR(\"<Idle\")); break;\n    case STATE_MOTION_CANCEL: // Report run state.\n    case STATE_CYCLE: printPgmString(PSTR(\"<Run\")); break;\n    case STATE_HOLD: printPgmString(PSTR(\"<Hold\")); break;\n    case STATE_HOMING: printPgmString(PSTR(\"<Home\")); break;\n    case STATE_ALARM: printPgmString(PSTR(\"<Alarm\")); break;\n    case STATE_CHECK_MODE: printPgmString(PSTR(\"<Check\")); break;\n    case STATE_SAFETY_DOOR: printPgmString(PSTR(\"<Door\")); break;\n  }\n \n  // If reporting a position, convert the current step count (current_position) to millimeters.\n  if (bit_istrue(settings.status_report_mask,(BITFLAG_RT_STATUS_MACHINE_POSITION | BITFLAG_RT_STATUS_WORK_POSITION))) {\n    system_convert_array_steps_to_mpos(print_position,current_position);\n  }\n  \n  // Report machine position\n  if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_MACHINE_POSITION)) {\n    printPgmString(PSTR(\",MPos:\")); \n    for (idx=0; idx< N_AXIS; idx++) {\n      printFloat_CoordValue(print_position[idx]);\n      if (idx < (N_AXIS-1)) { printPgmString(PSTR(\",\")); }\n    }\n  }\n  \n  // Report work position\n  if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_WORK_POSITION)) {\n    printPgmString(PSTR(\",WPos:\")); \n    for (idx=0; idx< N_AXIS; idx++) {\n      // Apply work coordinate offsets and tool length offset to current position.\n      print_position[idx] -= gc_state.coord_system[idx]+gc_state.coord_offset[idx];\n      if (idx == TOOL_LENGTH_OFFSET_AXIS) { print_position[idx] -= gc_state.tool_length_offset; }    \n      printFloat_CoordValue(print_position[idx]);\n      if (idx < (N_AXIS-1)) { printPgmString(PSTR(\",\")); }\n    }\n  }\n        \n  // Returns the number of active blocks are in the planner buffer.\n  if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_PLANNER_BUFFER)) {\n    printPgmString(PSTR(\",Buf:\"));\n    print_uint8_base10(plan_get_block_buffer_count());\n  }\n\n  // Report serial read buffer status\n  if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_SERIAL_RX)) {\n    printPgmString(PSTR(\",RX:\"));\n    print_uint8_base10(serial_get_rx_buffer_count());\n  }\n    \n  #ifdef USE_LINE_NUMBERS\n    // Report current line number\n    printPgmString(PSTR(\",Ln:\")); \n    int32_t ln=0;\n    plan_block_t * pb = plan_get_current_block();\n    if(pb != NULL) {\n      ln = pb->line_number;\n    } \n    printInteger(ln);\n  #endif\n    \n  #ifdef REPORT_REALTIME_RATE\n    // Report realtime rate \n    printPgmString(PSTR(\",F:\")); \n    printFloat_RateValue(st_get_realtime_rate());\n  #endif    \n  \n  if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_LIMIT_PINS)) {\n    printPgmString(PSTR(\",Lim:\"));\n    print_unsigned_int8(limits_get_state(),2,N_AXIS);\n  }\n  \n  #ifdef REPORT_CONTROL_PIN_STATE \n    printPgmString(PSTR(\",Ctl:\"));\n    print_uint8_base2(CONTROL_PIN & CONTROL_MASK);\n  #endif\n  \n  printPgmString(PSTR(\">\\r\\n\"));\n}\n"
  },
  {
    "path": "report.h",
    "content": "/*\n  report.h - reporting and messaging methods\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n#ifndef report_h\n#define report_h\n\n// Define Grbl status codes.\n#define STATUS_OK 0\n#define STATUS_EXPECTED_COMMAND_LETTER 1\n#define STATUS_BAD_NUMBER_FORMAT 2\n#define STATUS_INVALID_STATEMENT 3\n#define STATUS_NEGATIVE_VALUE 4\n#define STATUS_SETTING_DISABLED 5\n#define STATUS_SETTING_STEP_PULSE_MIN 6\n#define STATUS_SETTING_READ_FAIL 7\n#define STATUS_IDLE_ERROR 8\n#define STATUS_ALARM_LOCK 9\n#define STATUS_SOFT_LIMIT_ERROR 10\n#define STATUS_OVERFLOW 11\n#define STATUS_MAX_STEP_RATE_EXCEEDED 12\n\n#define STATUS_GCODE_UNSUPPORTED_COMMAND 20\n#define STATUS_GCODE_MODAL_GROUP_VIOLATION 21\n#define STATUS_GCODE_UNDEFINED_FEED_RATE 22\n#define STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER 23\n#define STATUS_GCODE_AXIS_COMMAND_CONFLICT 24\n#define STATUS_GCODE_WORD_REPEATED 25\n#define STATUS_GCODE_NO_AXIS_WORDS 26\n#define STATUS_GCODE_INVALID_LINE_NUMBER 27\n#define STATUS_GCODE_VALUE_WORD_MISSING 28\n#define STATUS_GCODE_UNSUPPORTED_COORD_SYS 29\n#define STATUS_GCODE_G53_INVALID_MOTION_MODE 30\n#define STATUS_GCODE_AXIS_WORDS_EXIST 31\n#define STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE 32\n#define STATUS_GCODE_INVALID_TARGET 33\n#define STATUS_GCODE_ARC_RADIUS_ERROR 34\n#define STATUS_GCODE_NO_OFFSETS_IN_PLANE 35\n#define STATUS_GCODE_UNUSED_WORDS 36\n#define STATUS_GCODE_G43_DYNAMIC_AXIS_ERROR 37\n\n// Define Grbl alarm codes.\n#define ALARM_HARD_LIMIT_ERROR 1\n#define ALARM_SOFT_LIMIT_ERROR 2\n#define ALARM_ABORT_CYCLE 3\n#define ALARM_PROBE_FAIL 4\n#define ALARM_HOMING_FAIL 5\n\n// Define Grbl feedback message codes.\n#define MESSAGE_CRITICAL_EVENT 1\n#define MESSAGE_ALARM_LOCK 2\n#define MESSAGE_ALARM_UNLOCK 3\n#define MESSAGE_ENABLED 4\n#define MESSAGE_DISABLED 5\n#define MESSAGE_SAFETY_DOOR_AJAR 6\n#define MESSAGE_PROGRAM_END 7\n#define MESSAGE_RESTORE_DEFAULTS 8\n\n// Prints system status messages.\nvoid report_status_message(uint8_t status_code);\n\n// Prints system alarm messages.\nvoid report_alarm_message(int8_t alarm_code);\n\n// Prints miscellaneous feedback messages.\nvoid report_feedback_message(uint8_t message_code);\n\n// Prints welcome message\nvoid report_init_message();\n\n// Prints Grbl help and current global settings\nvoid report_grbl_help();\n\n// Prints Grbl global settings\nvoid report_grbl_settings();\n\n// Prints an echo of the pre-parsed line received right before execution.\nvoid report_echo_line_received(char *line);\n\n// Prints realtime status report\nvoid report_realtime_status();\n\n// Prints recorded probe position\nvoid report_probe_parameters();\n\n// Prints Grbl NGC parameters (coordinate offsets, probe)\nvoid report_ngc_parameters();\n\n// Prints current g-code parser mode state\nvoid report_gcode_modes();\n\n// Prints startup line\nvoid report_startup_line(uint8_t n, char *line);\n\n// Prints build info and user info\nvoid report_build_info(char *line);\n\n#endif\n"
  },
  {
    "path": "serial.c",
    "content": "/*\n  serial.c - Low level functions for sending and recieving bytes via the serial port\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"grbl.h\"\n\n\nuint8_t serial_rx_buffer[RX_BUFFER_SIZE];\nuint8_t serial_rx_buffer_head = 0;\nvolatile uint8_t serial_rx_buffer_tail = 0;\n\nuint8_t serial_tx_buffer[TX_BUFFER_SIZE];\nuint8_t serial_tx_buffer_head = 0;\nvolatile uint8_t serial_tx_buffer_tail = 0;\n\n\n#ifdef ENABLE_XONXOFF\n  volatile uint8_t flow_ctrl = XON_SENT; // Flow control state variable\n#endif\n  \n\n// Returns the number of bytes used in the RX serial buffer.\nuint8_t serial_get_rx_buffer_count()\n{\n  uint8_t rtail = serial_rx_buffer_tail; // Copy to limit multiple calls to volatile\n  if (serial_rx_buffer_head >= rtail) { return(serial_rx_buffer_head-rtail); }\n  return (RX_BUFFER_SIZE - (rtail-serial_rx_buffer_head));\n}\n\n\n// Returns the number of bytes used in the TX serial buffer.\n// NOTE: Not used except for debugging and ensuring no TX bottlenecks.\nuint8_t serial_get_tx_buffer_count()\n{\n  uint8_t ttail = serial_tx_buffer_tail; // Copy to limit multiple calls to volatile\n  if (serial_tx_buffer_head >= ttail) { return(serial_tx_buffer_head-ttail); }\n  return (TX_BUFFER_SIZE - (ttail-serial_tx_buffer_head));\n}\n\n\nvoid serial_init()\n{\n  // Set baud rate\n  #if BAUD_RATE < 57600\n    uint16_t UBRR0_value = ((F_CPU / (8L * BAUD_RATE)) - 1)/2 ;\n    UCSR0A &= ~(1 << U2X0); // baud doubler off  - Only needed on Uno XXX\n  #else\n    uint16_t UBRR0_value = ((F_CPU / (4L * BAUD_RATE)) - 1)/2;\n    UCSR0A |= (1 << U2X0);  // baud doubler on for high baud rates, i.e. 115200\n  #endif\n  UBRR0H = UBRR0_value >> 8;\n  UBRR0L = UBRR0_value;\n            \n  // enable rx and tx\n  UCSR0B |= 1<<RXEN0;\n  UCSR0B |= 1<<TXEN0;\n\t\n  // enable interrupt on complete reception of a byte\n  UCSR0B |= 1<<RXCIE0;\n\t  \n  // defaults to 8-bit, no parity, 1 stop bit\n}\n\n\n// Writes one byte to the TX serial buffer. Called by main program.\n// TODO: Check if we can speed this up for writing strings, rather than single bytes.\nvoid serial_write(uint8_t data) {\n  // Calculate next head\n  uint8_t next_head = serial_tx_buffer_head + 1;\n  if (next_head == TX_BUFFER_SIZE) { next_head = 0; }\n\n  // Wait until there is space in the buffer\n  while (next_head == serial_tx_buffer_tail) { \n    // TODO: Restructure st_prep_buffer() calls to be executed here during a long print.    \n    if (sys.rt_exec_state & EXEC_RESET) { return; } // Only check for abort to avoid an endless loop.\n  }\n\n  // Store data and advance head\n  serial_tx_buffer[serial_tx_buffer_head] = data;\n  serial_tx_buffer_head = next_head;\n  \n  // Enable Data Register Empty Interrupt to make sure tx-streaming is running\n  UCSR0B |=  (1 << UDRIE0); \n}\n\n\n// Data Register Empty Interrupt handler\nISR(SERIAL_UDRE)\n{\n  uint8_t tail = serial_tx_buffer_tail; // Temporary serial_tx_buffer_tail (to optimize for volatile)\n  \n  #ifdef ENABLE_XONXOFF\n    if (flow_ctrl == SEND_XOFF) { \n      UDR0 = XOFF_CHAR; \n      flow_ctrl = XOFF_SENT; \n    } else if (flow_ctrl == SEND_XON) { \n      UDR0 = XON_CHAR; \n      flow_ctrl = XON_SENT; \n    } else\n  #endif\n  { \n    // Send a byte from the buffer\t\n    UDR0 = serial_tx_buffer[tail];\n  \n    // Update tail position\n    tail++;\n    if (tail == TX_BUFFER_SIZE) { tail = 0; }\n  \n    serial_tx_buffer_tail = tail;\n  }\n  \n  // Turn off Data Register Empty Interrupt to stop tx-streaming if this concludes the transfer\n  if (tail == serial_tx_buffer_head) { UCSR0B &= ~(1 << UDRIE0); }\n}\n\n\n// Fetches the first byte in the serial read buffer. Called by main program.\nuint8_t serial_read()\n{\n  uint8_t tail = serial_rx_buffer_tail; // Temporary serial_rx_buffer_tail (to optimize for volatile)\n  if (serial_rx_buffer_head == tail) {\n    return SERIAL_NO_DATA;\n  } else {\n    uint8_t data = serial_rx_buffer[tail];\n    \n    tail++;\n    if (tail == RX_BUFFER_SIZE) { tail = 0; }\n    serial_rx_buffer_tail = tail;\n\n    #ifdef ENABLE_XONXOFF\n      if ((serial_get_rx_buffer_count() < RX_BUFFER_LOW) && flow_ctrl == XOFF_SENT) { \n        flow_ctrl = SEND_XON;\n        UCSR0B |=  (1 << UDRIE0); // Force TX\n      }\n    #endif\n    \n    return data;\n  }\n}\n\n\nISR(SERIAL_RX)\n{\n  uint8_t data = UDR0;\n  uint8_t next_head;\n  \n  // Pick off realtime command characters directly from the serial stream. These characters are\n  // not passed into the buffer, but these set system state flag bits for realtime execution.\n  switch (data) {\n    case CMD_STATUS_REPORT: bit_true_atomic(sys.rt_exec_state, EXEC_STATUS_REPORT); break; // Set as true\n    case CMD_CYCLE_START:   bit_true_atomic(sys.rt_exec_state, EXEC_CYCLE_START); break; // Set as true\n    case CMD_FEED_HOLD:     bit_true_atomic(sys.rt_exec_state, EXEC_FEED_HOLD); break; // Set as true\n    case CMD_SAFETY_DOOR:   bit_true_atomic(sys.rt_exec_state, EXEC_SAFETY_DOOR); break; // Set as true\n    case CMD_RESET:         mc_reset(); break; // Call motion control reset routine.\n    default: // Write character to buffer    \n      next_head = serial_rx_buffer_head + 1;\n      if (next_head == RX_BUFFER_SIZE) { next_head = 0; }\n    \n      // Write data to buffer unless it is full.\n      if (next_head != serial_rx_buffer_tail) {\n        serial_rx_buffer[serial_rx_buffer_head] = data;\n        serial_rx_buffer_head = next_head;    \n        \n        #ifdef ENABLE_XONXOFF\n          if ((serial_get_rx_buffer_count() >= RX_BUFFER_FULL) && flow_ctrl == XON_SENT) {\n            flow_ctrl = SEND_XOFF;\n            UCSR0B |=  (1 << UDRIE0); // Force TX\n          } \n        #endif\n        \n      }\n      //TODO: else alarm on overflow?\n  }\n}\n\n\nvoid serial_reset_read_buffer() \n{\n  serial_rx_buffer_tail = serial_rx_buffer_head;\n\n  #ifdef ENABLE_XONXOFF\n    flow_ctrl = XON_SENT;\n  #endif\n}\n"
  },
  {
    "path": "serial.h",
    "content": "/*\n  serial.c - Low level functions for sending and recieving bytes via the serial port\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef serial_h\n#define serial_h\n\n\n#ifndef RX_BUFFER_SIZE\n  #define RX_BUFFER_SIZE 128\n#endif\n#ifndef TX_BUFFER_SIZE\n  #define TX_BUFFER_SIZE 64\n#endif\n\n#define SERIAL_NO_DATA 0xff\n\n#ifdef ENABLE_XONXOFF\n  #define RX_BUFFER_FULL 96 // XOFF high watermark\n  #define RX_BUFFER_LOW 64 // XON low watermark\n  #define SEND_XOFF 1\n  #define SEND_XON 2\n  #define XOFF_SENT 3\n  #define XON_SENT 4\n  #define XOFF_CHAR 0x13\n  #define XON_CHAR 0x11\n#endif\n\nvoid serial_init();\n\n// Writes one byte to the TX serial buffer. Called by main program.\nvoid serial_write(uint8_t data);\n\n// Fetches the first byte in the serial read buffer. Called by main program.\nuint8_t serial_read();\n\n// Reset and empty data in read buffer. Used by e-stop and reset.\nvoid serial_reset_read_buffer();\n\n// Returns the number of bytes used in the RX serial buffer.\nuint8_t serial_get_rx_buffer_count();\n\n// Returns the number of bytes used in the TX serial buffer.\n// NOTE: Not used except for debugging and ensuring no TX bottlenecks.\nuint8_t serial_get_tx_buffer_count();\n\n#endif\n"
  },
  {
    "path": "settings.c",
    "content": "/*\n  settings.c - eeprom configuration handling \n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon  \n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"grbl.h\"\n\nsettings_t settings;\n\n\n// Method to store startup lines into EEPROM\nvoid settings_store_startup_line(uint8_t n, char *line)\n{\n  uint32_t addr = n*(LINE_BUFFER_SIZE+1)+EEPROM_ADDR_STARTUP_BLOCK;\n  memcpy_to_eeprom_with_checksum(addr,(char*)line, LINE_BUFFER_SIZE);\n}\n\n\n// Method to store build info into EEPROM\nvoid settings_store_build_info(char *line)\n{\n  memcpy_to_eeprom_with_checksum(EEPROM_ADDR_BUILD_INFO,(char*)line, LINE_BUFFER_SIZE);\n}\n\n\n// Method to store coord data parameters into EEPROM\nvoid settings_write_coord_data(uint8_t coord_select, float *coord_data)\n{  \n  uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS;\n  memcpy_to_eeprom_with_checksum(addr,(char*)coord_data, sizeof(float)*N_AXIS);\n}  \n\n\n// Method to store Grbl global settings struct and version number into EEPROM\nvoid write_global_settings() \n{\n  eeprom_put_char(0, SETTINGS_VERSION);\n  memcpy_to_eeprom_with_checksum(EEPROM_ADDR_GLOBAL, (char*)&settings, sizeof(settings_t));\n}\n\n\n// Method to restore EEPROM-saved Grbl global settings back to defaults. \nvoid settings_restore(uint8_t restore_flag) {  \n  if (restore_flag & SETTINGS_RESTORE_DEFAULTS) {\n\tsettings.pulse_microseconds = DEFAULT_STEP_PULSE_MICROSECONDS;\n\tsettings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME;\n\tsettings.step_invert_mask = DEFAULT_STEPPING_INVERT_MASK;\n\tsettings.dir_invert_mask = DEFAULT_DIRECTION_INVERT_MASK;\n\tsettings.status_report_mask = DEFAULT_STATUS_REPORT_MASK;\n\tsettings.junction_deviation = DEFAULT_JUNCTION_DEVIATION;\n\tsettings.arc_tolerance = DEFAULT_ARC_TOLERANCE;\n\tsettings.homing_dir_mask = DEFAULT_HOMING_DIR_MASK;\n\tsettings.homing_feed_rate = DEFAULT_HOMING_FEED_RATE;\n\tsettings.homing_seek_rate = DEFAULT_HOMING_SEEK_RATE;\n\tsettings.homing_debounce_delay = DEFAULT_HOMING_DEBOUNCE_DELAY;\n\tsettings.homing_pulloff = DEFAULT_HOMING_PULLOFF;\n\n\tsettings.flags = 0;\n\tif (DEFAULT_REPORT_INCHES) { settings.flags |= BITFLAG_REPORT_INCHES; }\n\tif (DEFAULT_INVERT_ST_ENABLE) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; }\n\tif (DEFAULT_INVERT_LIMIT_PINS) { settings.flags |= BITFLAG_INVERT_LIMIT_PINS; }\n\tif (DEFAULT_SOFT_LIMIT_ENABLE) { settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; }\n\tif (DEFAULT_HARD_LIMIT_ENABLE) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; }\n\tif (DEFAULT_HOMING_ENABLE) { settings.flags |= BITFLAG_HOMING_ENABLE; }\n  \n\tsettings.steps_per_mm[X_AXIS] = DEFAULT_X_STEPS_PER_MM;\n\tsettings.steps_per_mm[Y_AXIS] = DEFAULT_Y_STEPS_PER_MM;\n\tsettings.steps_per_mm[Z_AXIS] = DEFAULT_Z_STEPS_PER_MM;\n\tsettings.max_rate[X_AXIS] = DEFAULT_X_MAX_RATE;\n\tsettings.max_rate[Y_AXIS] = DEFAULT_Y_MAX_RATE;\n\tsettings.max_rate[Z_AXIS] = DEFAULT_Z_MAX_RATE;\n\tsettings.acceleration[X_AXIS] = DEFAULT_X_ACCELERATION;\n\tsettings.acceleration[Y_AXIS] = DEFAULT_Y_ACCELERATION;\n\tsettings.acceleration[Z_AXIS] = DEFAULT_Z_ACCELERATION;\n\tsettings.max_travel[X_AXIS] = (-DEFAULT_X_MAX_TRAVEL);\n\tsettings.max_travel[Y_AXIS] = (-DEFAULT_Y_MAX_TRAVEL);\n\tsettings.max_travel[Z_AXIS] = (-DEFAULT_Z_MAX_TRAVEL);    \n\n\twrite_global_settings();\n  }\n  \n  if (restore_flag & SETTINGS_RESTORE_PARAMETERS) {\n\tuint8_t idx;\n\tfloat coord_data[N_AXIS];\n\tmemset(&coord_data, 0, sizeof(coord_data));\n\tfor (idx=0; idx <= SETTING_INDEX_NCOORD; idx++) { settings_write_coord_data(idx, coord_data); }\n  }\n  \n  if (restore_flag & SETTINGS_RESTORE_STARTUP_LINES) {\n\t#if N_STARTUP_LINE > 0\n\teeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK, 0);\n\t#endif\n\t#if N_STARTUP_LINE > 1\n\teeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+(LINE_BUFFER_SIZE+1), 0);\n\t#endif\n  }\n  \n  if (restore_flag & SETTINGS_RESTORE_BUILD_INFO) { eeprom_put_char(EEPROM_ADDR_BUILD_INFO , 0); }\n}\n\n\n// Reads startup line from EEPROM. Updated pointed line string data.\nuint8_t settings_read_startup_line(uint8_t n, char *line)\n{\n  uint32_t addr = n*(LINE_BUFFER_SIZE+1)+EEPROM_ADDR_STARTUP_BLOCK;\n  if (!(memcpy_from_eeprom_with_checksum((char*)line, addr, LINE_BUFFER_SIZE))) {\n    // Reset line with default value\n    line[0] = 0; // Empty line\n    settings_store_startup_line(n, line);\n    return(false);\n  }\n  return(true);\n}\n\n\n// Reads startup line from EEPROM. Updated pointed line string data.\nuint8_t settings_read_build_info(char *line)\n{\n  if (!(memcpy_from_eeprom_with_checksum((char*)line, EEPROM_ADDR_BUILD_INFO, LINE_BUFFER_SIZE))) {\n    // Reset line with default value\n    line[0] = 0; // Empty line\n    settings_store_build_info(line);\n    return(false);\n  }\n  return(true);\n}\n\n\n// Read selected coordinate data from EEPROM. Updates pointed coord_data value.\nuint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data)\n{\n  uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS;\n  if (!(memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float)*N_AXIS))) {\n    // Reset with default zero vector\n    clear_vector_float(coord_data); \n    settings_write_coord_data(coord_select,coord_data);\n    return(false);\n  }\n  return(true);\n}  \n\n\n// Reads Grbl global settings struct from EEPROM.\nuint8_t read_global_settings() {\n  // Check version-byte of eeprom\n  uint8_t version = eeprom_get_char(0);\n  if (version == SETTINGS_VERSION) {\n    // Read settings-record and check checksum\n    if (!(memcpy_from_eeprom_with_checksum((char*)&settings, EEPROM_ADDR_GLOBAL, sizeof(settings_t)))) {\n      return(false);\n    }\n  } else {\n    return(false); \n  }\n  return(true);\n}\n\n\n// A helper method to set settings from command line\nuint8_t settings_store_global_setting(uint8_t parameter, float value) {\n  if (value < 0.0) { return(STATUS_NEGATIVE_VALUE); } \n  if (parameter >= AXIS_SETTINGS_START_VAL) {\n    // Store axis configuration. Axis numbering sequence set by AXIS_SETTING defines.\n    // NOTE: Ensure the setting index corresponds to the report.c settings printout.\n    parameter -= AXIS_SETTINGS_START_VAL;\n    uint8_t set_idx = 0;\n    while (set_idx < AXIS_N_SETTINGS) {\n      if (parameter < N_AXIS) {\n        // Valid axis setting found.\n        switch (set_idx) {\n          case 0:\n            #ifdef MAX_STEP_RATE_HZ\n              if (value*settings.max_rate[parameter] > (MAX_STEP_RATE_HZ*60.0)) { return(STATUS_MAX_STEP_RATE_EXCEEDED); }\n            #endif\n            settings.steps_per_mm[parameter] = value;\n            break;\n          case 1:\n            #ifdef MAX_STEP_RATE_HZ\n              if (value*settings.steps_per_mm[parameter] > (MAX_STEP_RATE_HZ*60.0)) {  return(STATUS_MAX_STEP_RATE_EXCEEDED); }\n            #endif\n            settings.max_rate[parameter] = value;\n            break;\n          case 2: settings.acceleration[parameter] = value*60*60; break; // Convert to mm/min^2 for grbl internal use.\n          case 3: settings.max_travel[parameter] = -value; break;  // Store as negative for grbl internal use.\n        }\n        break; // Exit while-loop after setting has been configured and proceed to the EEPROM write call.\n      } else {\n        set_idx++;\n        // If axis index greater than N_AXIS or setting index greater than number of axis settings, error out.\n        if ((parameter < AXIS_SETTINGS_INCREMENT) || (set_idx == AXIS_N_SETTINGS)) { return(STATUS_INVALID_STATEMENT); }\n        parameter -= AXIS_SETTINGS_INCREMENT;\n      }\n    }\n  } else {\n    // Store non-axis Grbl settings\n    uint8_t int_value = trunc(value);\n    switch(parameter) {\n      case 0: \n        if (int_value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); }\n        settings.pulse_microseconds = int_value; break;\n      case 1: settings.stepper_idle_lock_time = int_value; break;\n      case 2: \n        settings.step_invert_mask = int_value; \n        st_generate_step_dir_invert_masks(); // Regenerate step and direction port invert masks.\n        break;\n      case 3: \n        settings.dir_invert_mask = int_value; \n        st_generate_step_dir_invert_masks(); // Regenerate step and direction port invert masks.\n        break;\n      case 4: // Reset to ensure change. Immediate re-init may cause problems.\n        if (int_value) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; }\n        else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; }\n        break;\n      case 5: // Reset to ensure change. Immediate re-init may cause problems.\n        if (int_value) { settings.flags |= BITFLAG_INVERT_LIMIT_PINS; }\n        else { settings.flags &= ~BITFLAG_INVERT_LIMIT_PINS; }\n        break;\n      case 6: // Reset to ensure change. Immediate re-init may cause problems.\n        if (int_value) { settings.flags |= BITFLAG_INVERT_PROBE_PIN; }\n        else { settings.flags &= ~BITFLAG_INVERT_PROBE_PIN; }\n        break;\n      case 10: settings.status_report_mask = int_value; break;\n      case 11: settings.junction_deviation = value; break;\n      case 12: settings.arc_tolerance = value; break;\n      case 13:\n        if (int_value) { settings.flags |= BITFLAG_REPORT_INCHES; }\n        else { settings.flags &= ~BITFLAG_REPORT_INCHES; }\n        break;\n      case 20:\n        if (int_value) { \n          if (bit_isfalse(settings.flags, BITFLAG_HOMING_ENABLE)) { return(STATUS_SOFT_LIMIT_ERROR); }\n          settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; \n        } else { settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; }\n        break;\n      case 21:\n        if (int_value) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; }\n        else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; }\n        limits_init(); // Re-init to immediately change. NOTE: Nice to have but could be problematic later.\n        break;\n      case 22:\n        if (int_value) { settings.flags |= BITFLAG_HOMING_ENABLE; }\n        else { \n          settings.flags &= ~BITFLAG_HOMING_ENABLE; \n          settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; // Force disable soft-limits.\n        }\n        break;\n      case 23: settings.homing_dir_mask = int_value; break;\n      case 24: settings.homing_feed_rate = value; break;\n      case 25: settings.homing_seek_rate = value; break;\n      case 26: settings.homing_debounce_delay = int_value; break;\n      case 27: settings.homing_pulloff = value; break;\n      default: \n        return(STATUS_INVALID_STATEMENT);\n    }\n  }\n  write_global_settings();\n  return(STATUS_OK);\n}\n\n\n// Initialize the config subsystem\nvoid settings_init() {\n  if(!read_global_settings()) {\n    report_status_message(STATUS_SETTING_READ_FAIL);\n    settings_restore(SETTINGS_RESTORE_ALL); // Force restore all EEPROM data.\n    report_grbl_settings();\n  }\n\n  // NOTE: Checking paramater data, startup lines, and build info string should be done here, \n  // but it seems fairly redundant. Each of these can be manually checked and reset or restored.\n  // Check all parameter data into a dummy variable. If error, reset to zero, otherwise do nothing.\n  // float coord_data[N_AXIS];\n  // uint8_t i;\n  // for (i=0; i<=SETTING_INDEX_NCOORD; i++) {\n  //   if (!settings_read_coord_data(i, coord_data)) {\n  // \treport_status_message(STATUS_SETTING_READ_FAIL);\n  //   }\n  // }\n  // NOTE: Startup lines are checked and executed by protocol_main_loop at the end of initialization.\n}\n\n\n// Returns step pin mask according to Grbl internal axis indexing.\nuint8_t get_step_pin_mask(uint8_t axis_idx)\n{\n  if ( axis_idx == X_AXIS ) { return((1<<X_STEP_BIT)); }\n  if ( axis_idx == Y_AXIS ) { return((1<<Y_STEP_BIT)); }\n  return((1<<Z_STEP_BIT));\n}\n\n\n// Returns direction pin mask according to Grbl internal axis indexing.\nuint8_t get_direction_pin_mask(uint8_t axis_idx)\n{\n  if ( axis_idx == X_AXIS ) { return((1<<X_DIRECTION_BIT)); }\n  if ( axis_idx == Y_AXIS ) { return((1<<Y_DIRECTION_BIT)); }\n  return((1<<Z_DIRECTION_BIT));\n}\n\n\n// Returns limit pin mask according to Grbl internal axis indexing.\nuint8_t get_limit_pin_mask(uint8_t axis_idx)\n{\n  if ( axis_idx == X_AXIS ) { return((1<<X_LIMIT_BIT)); }\n  if ( axis_idx == Y_AXIS ) { return((1<<Y_LIMIT_BIT)); }\n  return((1<<Z_LIMIT_BIT));\n}\n"
  },
  {
    "path": "settings.h",
    "content": "/*\n  settings.h - eeprom configuration handling \n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n  \n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef settings_h\n#define settings_h\n\n#include \"grbl.h\"\n\n\n// Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl\n// when firmware is upgraded. Always stored in byte 0 of eeprom\n#define SETTINGS_VERSION 9  // NOTE: Check settings_reset() when moving to next version.\n\n// Define bit flag masks for the boolean settings in settings.flag.\n#define BITFLAG_REPORT_INCHES      bit(0)\n// #define BITFLAG_AUTO_START         bit(1) // Obsolete. Don't alter to keep back compatibility.\n#define BITFLAG_INVERT_ST_ENABLE   bit(2)\n#define BITFLAG_HARD_LIMIT_ENABLE  bit(3)\n#define BITFLAG_HOMING_ENABLE      bit(4)\n#define BITFLAG_SOFT_LIMIT_ENABLE  bit(5)\n#define BITFLAG_INVERT_LIMIT_PINS  bit(6)\n#define BITFLAG_INVERT_PROBE_PIN   bit(7)\n\n// Define status reporting boolean enable bit flags in settings.status_report_mask\n#define BITFLAG_RT_STATUS_MACHINE_POSITION  bit(0)\n#define BITFLAG_RT_STATUS_WORK_POSITION     bit(1)\n#define BITFLAG_RT_STATUS_PLANNER_BUFFER    bit(2)\n#define BITFLAG_RT_STATUS_SERIAL_RX         bit(3)\n#define BITFLAG_RT_STATUS_LIMIT_PINS        bit(4)\n\n// Define settings restore bitflags.\n#define SETTINGS_RESTORE_ALL 0xFF // All bitflags\n#define SETTINGS_RESTORE_DEFAULTS bit(0)\n#define SETTINGS_RESTORE_PARAMETERS bit(1)\n#define SETTINGS_RESTORE_STARTUP_LINES bit(2)\n#define SETTINGS_RESTORE_BUILD_INFO bit(3)\n\n// Define EEPROM memory address location values for Grbl settings and parameters\n// NOTE: The Atmega328p has 1KB EEPROM. The upper half is reserved for parameters and\n// the startup script. The lower half contains the global settings and space for future \n// developments.\n#define EEPROM_ADDR_GLOBAL         1U\n#define EEPROM_ADDR_PARAMETERS     512U\n#define EEPROM_ADDR_STARTUP_BLOCK  768U\n#define EEPROM_ADDR_BUILD_INFO     942U\n\n// Define EEPROM address indexing for coordinate parameters\n#define N_COORDINATE_SYSTEM 6  // Number of supported work coordinate systems (from index 1)\n#define SETTING_INDEX_NCOORD N_COORDINATE_SYSTEM+1 // Total number of system stored (from index 0)\n// NOTE: Work coordinate indices are (0=G54, 1=G55, ... , 6=G59)\n#define SETTING_INDEX_G28    N_COORDINATE_SYSTEM    // Home position 1\n#define SETTING_INDEX_G30    N_COORDINATE_SYSTEM+1  // Home position 2\n// #define SETTING_INDEX_G92    N_COORDINATE_SYSTEM+2  // Coordinate offset (G92.2,G92.3 not supported)\n\n// Define Grbl axis settings numbering scheme. Starts at START_VAL, every INCREMENT, over N_SETTINGS.\n#define AXIS_N_SETTINGS          4\n#define AXIS_SETTINGS_START_VAL  100 // NOTE: Reserving settings values >= 100 for axis settings. Up to 255.\n#define AXIS_SETTINGS_INCREMENT  10  // Must be greater than the number of axis settings\n\n// Global persistent settings (Stored from byte EEPROM_ADDR_GLOBAL onwards)\ntypedef struct {\n  // Axis settings\n  float steps_per_mm[N_AXIS];\n  float max_rate[N_AXIS];\n  float acceleration[N_AXIS];\n  float max_travel[N_AXIS];\n\n  // Remaining Grbl settings\n  uint8_t pulse_microseconds;\n  uint8_t step_invert_mask;\n  uint8_t dir_invert_mask;\n  uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable.\n  uint8_t status_report_mask; // Mask to indicate desired report data.\n  float junction_deviation;\n  float arc_tolerance;\n  \n  uint8_t flags;  // Contains default boolean settings\n\n  uint8_t homing_dir_mask;\n  float homing_feed_rate;\n  float homing_seek_rate;\n  uint16_t homing_debounce_delay;\n  float homing_pulloff;\n} settings_t;\nextern settings_t settings;\n\n// Initialize the configuration subsystem (load settings from EEPROM)\nvoid settings_init();\n\n// Helper function to clear and restore EEPROM defaults\nvoid settings_restore(uint8_t restore_flag);\n\n// A helper method to set new settings from command line\nuint8_t settings_store_global_setting(uint8_t parameter, float value);\n\n// Stores the protocol line variable as a startup line in EEPROM\nvoid settings_store_startup_line(uint8_t n, char *line);\n\n// Reads an EEPROM startup line to the protocol line variable\nuint8_t settings_read_startup_line(uint8_t n, char *line);\n\n// Stores build info user-defined string\nvoid settings_store_build_info(char *line);\n\n// Reads build info user-defined string\nuint8_t settings_read_build_info(char *line);\n\n// Writes selected coordinate data to EEPROM\nvoid settings_write_coord_data(uint8_t coord_select, float *coord_data);\n\n// Reads selected coordinate data from EEPROM\nuint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data);\n\n// Returns the step pin mask according to Grbl's internal axis numbering\nuint8_t get_step_pin_mask(uint8_t i);\n\n// Returns the direction pin mask according to Grbl's internal axis numbering\nuint8_t get_direction_pin_mask(uint8_t i);\n\n// Returns the limit pin mask according to Grbl's internal axis numbering\nuint8_t get_limit_pin_mask(uint8_t i);\n\n\n#endif\n"
  },
  {
    "path": "spindle_control.c",
    "content": "/*\n  spindle_control.c - spindle control methods\n  Part of Grbl\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/* RC-Servo PWM modification: switch between 0.6ms and 2.5ms pulse-width at 61Hz\n   Prescaler 1024 = 15625Hz / 256Steps =  61Hz\t64µs/step -> Values 15 / 32 for 1ms / 2ms\n   Reload value = 0x07 \n   Replace this file in C:\\Program Files (x86)\\Arduino\\libraries\\GRBL\n*/\n\n\n#include \"grbl.h\"\n\n#define RC_SERVO_SHORT     15       // Timer ticks for 0.6ms pulse duration  (9 for 0.6ms)\n#define RC_SERVO_LONG      32       // Timer ticks for 2.5 ms pulse duration  (39 for 2.5ms)     \n//#define RC_SERVO_INVERT     1     // Uncomment to invert servo direction\n\n\nvoid spindle_init()\n{    \n  // Configure variable spindle PWM and enable pin, if requried. On the Uno, PWM and enable are\n  // combined unless configured otherwise.\n  #ifdef VARIABLE_SPINDLE\n    SPINDLE_PWM_DDR |= (1<<SPINDLE_PWM_BIT); // Configure as PWM output pin.\n    #if defined(CPU_MAP_ATMEGA2560) || defined(USE_SPINDLE_DIR_AS_ENABLE_PIN)\n      SPINDLE_ENABLE_DDR |= (1<<SPINDLE_ENABLE_BIT); // Configure as output pin.\n    #endif     \n  // Configure no variable spindle and only enable pin.\n  #else  \n    SPINDLE_ENABLE_DDR |= (1<<SPINDLE_ENABLE_BIT); // Configure as output pin.\n  #endif\n  \n  #ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN\n    SPINDLE_DIRECTION_DDR |= (1<<SPINDLE_DIRECTION_BIT); // Configure as output pin.\n  #endif\n  spindle_stop();\n}\n\n\nvoid spindle_stop()\n{     // On the Uno, spindle enable and PWM are shared. Other CPUs have seperate enable pin.\n       #ifdef RC_SERVO_INVERT \n          OCR_REGISTER = RC_SERVO_LONG;\n      #else\n          OCR_REGISTER = RC_SERVO_SHORT;\n      #endif    \n}\n\n\nvoid spindle_run(uint8_t direction, float rpm) \n{\n  if (sys.state == STATE_CHECK_MODE) { return; }\n  \n  // Empty planner buffer to ensure spindle is set when programmed.\n  protocol_auto_cycle_start();  //temp fix for M3 lockup\n  protocol_buffer_synchronize(); \n  \n  if (direction == SPINDLE_DISABLE) {\n\n    spindle_stop();\n\n  } else {\n\t#ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN\n\n    if (direction == SPINDLE_ENABLE_CW) {\n      SPINDLE_DIRECTION_PORT &= ~(1<<SPINDLE_DIRECTION_BIT);\n    } else {\n      SPINDLE_DIRECTION_PORT |= (1<<SPINDLE_DIRECTION_BIT);\n    }\n\t#endif\n\t\n\t#ifdef VARIABLE_SPINDLE\n   \n      // TODO: Install the optional capability for frequency-based output for servos.\n      #define SPINDLE_RPM_RANGE (SPINDLE_MAX_RPM-SPINDLE_MIN_RPM)\n      #define RC_SERVO_RANGE (RC_SERVO_LONG-RC_SERVO_SHORT)\n\t  \n\t  #ifdef CPU_MAP_ATMEGA2560\n      \tTCCRA_REGISTER = (1<<COMB_BIT) | (1<<WAVE1_REGISTER) | (1<<WAVE0_REGISTER);\n        TCCRB_REGISTER = (TCCRB_REGISTER & 0b11111000) | 0x07 | (1<<WAVE2_REGISTER) | (1<<WAVE3_REGISTER); // set to 1/1024 Prescaler\n        OCR4A = 0xFFFF; // set the top 16bit value\n        uint16_t current_pwm;\n\t  #else\n        TCCRA_REGISTER = (1<<COMB_BIT) | (1<<WAVE1_REGISTER) | (1<<WAVE0_REGISTER);\n        TCCRB_REGISTER = (TCCRB_REGISTER & 0b11111000) | 0x07; // set to 1/1024 Prescaler\n\t    uint8_t current_pwm;\n\t  #endif\n\n\t   if ( rpm < SPINDLE_MIN_RPM ) { rpm = 0; } \n      else { \n        rpm -= SPINDLE_MIN_RPM; \n        if ( rpm > SPINDLE_RPM_RANGE ) { rpm = SPINDLE_RPM_RANGE; } // Prevent integer overflow\n      }\n\t  \n      #ifdef RC_SERVO_INVERT \n          current_pwm = floor( RC_SERVO_LONG - rpm*(RC_SERVO_RANGE/SPINDLE_RPM_RANGE));\n          OCR_REGISTER = current_pwm;\n      #else\n         current_pwm = floor( rpm*(RC_SERVO_RANGE/SPINDLE_RPM_RANGE) + RC_SERVO_SHORT);\n          OCR_REGISTER = current_pwm;\n      #endif    \n\t  #ifdef MINIMUM_SPINDLE_PWM\n        if (current_pwm < MINIMUM_SPINDLE_PWM) { current_pwm = MINIMUM_SPINDLE_PWM; }\n\t     OCR_REGISTER = current_pwm;\n      #endif \n    #endif  \n  }\n}\nspindle_set_state(uint8_t state, float rpm){\n}"
  },
  {
    "path": "spindle_control.h",
    "content": "/*\n  spindle_control.h - spindle control methods\n  Part of Grbl\n\n  Copyright (c) 2012-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/ \n\n#ifndef spindle_control_h\n#define spindle_control_h \n\n\n// Initializes spindle pins and hardware PWM, if enabled.\nvoid spindle_init();\n\n// Sets spindle direction and spindle rpm via PWM, if enabled.\nvoid spindle_run(uint8_t direction, float rpm);\n\nvoid spindle_set_state(uint8_t state, float rpm);\n\n// Kills spindle.\nvoid spindle_stop();\n\n#endif\n"
  },
  {
    "path": "stepper.c",
    "content": "/*\n  stepper.c - stepper motor driver: executes motion plans using stepper motors\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n  \n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"grbl.h\"\n\n\n// Some useful constants.\n#define DT_SEGMENT (1.0/(ACCELERATION_TICKS_PER_SECOND*60.0)) // min/segment \n#define REQ_MM_INCREMENT_SCALAR 1.25                                   \n#define RAMP_ACCEL 0\n#define RAMP_CRUISE 1\n#define RAMP_DECEL 2\n\n// Define Adaptive Multi-Axis Step-Smoothing(AMASS) levels and cutoff frequencies. The highest level\n// frequency bin starts at 0Hz and ends at its cutoff frequency. The next lower level frequency bin\n// starts at the next higher cutoff frequency, and so on. The cutoff frequencies for each level must\n// be considered carefully against how much it over-drives the stepper ISR, the accuracy of the 16-bit\n// timer, and the CPU overhead. Level 0 (no AMASS, normal operation) frequency bin starts at the \n// Level 1 cutoff frequency and up to as fast as the CPU allows (over 30kHz in limited testing).\n// NOTE: AMASS cutoff frequency multiplied by ISR overdrive factor must not exceed maximum step frequency.\n// NOTE: Current settings are set to overdrive the ISR to no more than 16kHz, balancing CPU overhead\n// and timer accuracy.  Do not alter these settings unless you know what you are doing.\n#define MAX_AMASS_LEVEL 3\n// AMASS_LEVEL0: Normal operation. No AMASS. No upper cutoff frequency. Starts at LEVEL1 cutoff frequency.\n#define AMASS_LEVEL1 (F_CPU/8000) // Over-drives ISR (x2). Defined as F_CPU/(Cutoff frequency in Hz)\n#define AMASS_LEVEL2 (F_CPU/4000) // Over-drives ISR (x4)\n#define AMASS_LEVEL3 (F_CPU/2000) // Over-drives ISR (x8)\n\n\n// Stores the planner block Bresenham algorithm execution data for the segments in the segment \n// buffer. Normally, this buffer is partially in-use, but, for the worst case scenario, it will\n// never exceed the number of accessible stepper buffer segments (SEGMENT_BUFFER_SIZE-1).\n// NOTE: This data is copied from the prepped planner blocks so that the planner blocks may be\n// discarded when entirely consumed and completed by the segment buffer. Also, AMASS alters this\n// data for its own use. \ntypedef struct {  \n  uint8_t direction_bits;\n  uint32_t steps[N_AXIS];\n  uint32_t step_event_count;\n} st_block_t;\nstatic st_block_t st_block_buffer[SEGMENT_BUFFER_SIZE-1];\n\n// Primary stepper segment ring buffer. Contains small, short line segments for the stepper \n// algorithm to execute, which are \"checked-out\" incrementally from the first block in the\n// planner buffer. Once \"checked-out\", the steps in the segments buffer cannot be modified by \n// the planner, where the remaining planner block steps still can.\ntypedef struct {\n  uint16_t n_step;          // Number of step events to be executed for this segment\n  uint8_t st_block_index;   // Stepper block data index. Uses this information to execute this segment.\n  uint16_t cycles_per_tick; // Step distance traveled per ISR tick, aka step rate.\n  #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING\n    uint8_t amass_level;    // Indicates AMASS level for the ISR to execute this segment\n  #else\n    uint8_t prescaler;      // Without AMASS, a prescaler is required to adjust for slow timing.\n  #endif\n} segment_t;\nstatic segment_t segment_buffer[SEGMENT_BUFFER_SIZE];\n\n// Stepper ISR data struct. Contains the running data for the main stepper ISR.\ntypedef struct {\n  // Used by the bresenham line algorithm\n  uint32_t counter_x,        // Counter variables for the bresenham line tracer\n           counter_y, \n           counter_z;\n  #ifdef STEP_PULSE_DELAY\n    uint8_t step_bits;  // Stores out_bits output to complete the step pulse delay\n  #endif\n  \n  uint8_t execute_step;     // Flags step execution for each interrupt.\n  uint8_t step_pulse_time;  // Step pulse reset time after step rise\n  uint8_t step_outbits;         // The next stepping-bits to be output\n  uint8_t dir_outbits;\n  #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING\n    uint32_t steps[N_AXIS];\n  #endif\n\n  uint16_t step_count;       // Steps remaining in line segment motion  \n  uint8_t exec_block_index; // Tracks the current st_block index. Change indicates new block.\n  st_block_t *exec_block;   // Pointer to the block data for the segment being executed\n  segment_t *exec_segment;  // Pointer to the segment being executed\n} stepper_t;\nstatic stepper_t st;\n\n// Step segment ring buffer indices\nstatic volatile uint8_t segment_buffer_tail;\nstatic uint8_t segment_buffer_head;\nstatic uint8_t segment_next_head;\n\n// Step and direction port invert masks. \nstatic uint8_t step_port_invert_mask;\nstatic uint8_t dir_port_invert_mask;\n\n// Used to avoid ISR nesting of the \"Stepper Driver Interrupt\". Should never occur though.\nstatic volatile uint8_t busy;   \n\n// Pointers for the step segment being prepped from the planner buffer. Accessed only by the\n// main program. Pointers may be planning segments or planner blocks ahead of what being executed.\nstatic plan_block_t *pl_block;     // Pointer to the planner block being prepped\nstatic st_block_t *st_prep_block;  // Pointer to the stepper block data being prepped \n\n// Segment preparation data struct. Contains all the necessary information to compute new segments\n// based on the current executing planner block.\ntypedef struct {\n  uint8_t st_block_index;  // Index of stepper common data block being prepped\n  uint8_t flag_partial_block;  // Flag indicating the last block completed. Time to load a new one.\n\n  float steps_remaining;\n  float step_per_mm;           // Current planner block step/millimeter conversion scalar\n  float req_mm_increment;\n  float dt_remainder;\n  \n  uint8_t ramp_type;      // Current segment ramp state\n  float mm_complete;      // End of velocity profile from end of current planner block in (mm).\n                          // NOTE: This value must coincide with a step(no mantissa) when converted.\n  float current_speed;    // Current speed at the end of the segment buffer (mm/min)\n  float maximum_speed;    // Maximum speed of executing block. Not always nominal speed. (mm/min)\n  float exit_speed;       // Exit speed of executing block (mm/min)\n  float accelerate_until; // Acceleration ramp end measured from end of block (mm)\n  float decelerate_after; // Deceleration ramp start measured from end of block (mm)\n} st_prep_t;\nstatic st_prep_t prep;\n\n\n/*    BLOCK VELOCITY PROFILE DEFINITION \n          __________________________\n         /|                        |\\     _________________         ^\n        / |                        | \\   /|               |\\        |\n       /  |                        |  \\ / |               | \\       s\n      /   |                        |   |  |               |  \\      p\n     /    |                        |   |  |               |   \\     e\n    +-----+------------------------+---+--+---------------+----+    e\n    |               BLOCK 1            ^      BLOCK 2          |    d\n                                       |\n                  time ----->      EXAMPLE: Block 2 entry speed is at max junction velocity\n  \n  The planner block buffer is planned assuming constant acceleration velocity profiles and are\n  continuously joined at block junctions as shown above. However, the planner only actively computes\n  the block entry speeds for an optimal velocity plan, but does not compute the block internal\n  velocity profiles. These velocity profiles are computed ad-hoc as they are executed by the \n  stepper algorithm and consists of only 7 possible types of profiles: cruise-only, cruise-\n  deceleration, acceleration-cruise, acceleration-only, deceleration-only, full-trapezoid, and \n  triangle(no cruise).\n\n                                        maximum_speed (< nominal_speed) ->  + \n                    +--------+ <- maximum_speed (= nominal_speed)          /|\\                                         \n                   /          \\                                           / | \\                      \n current_speed -> +            \\                                         /  |  + <- exit_speed\n                  |             + <- exit_speed                         /   |  |                       \n                  +-------------+                     current_speed -> +----+--+                   \n                   time -->  ^  ^                                           ^  ^                       \n                             |  |                                           |  |                       \n                decelerate_after(in mm)                             decelerate_after(in mm)\n                    ^           ^                                           ^  ^\n                    |           |                                           |  |\n                accelerate_until(in mm)                             accelerate_until(in mm)\n                    \n  The step segment buffer computes the executing block velocity profile and tracks the critical\n  parameters for the stepper algorithm to accurately trace the profile. These critical parameters \n  are shown and defined in the above illustration.\n*/\n\n\n// Stepper state initialization. Cycle should only start if the st.cycle_start flag is\n// enabled. Startup init and limits call this function but shouldn't start the cycle.\nvoid st_wake_up() \n{\n  // Enable stepper drivers.\n  if (bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)) { STEPPERS_DISABLE_PORT |= (1<<STEPPERS_DISABLE_BIT); }\n  else { STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT); }\n\n  if (sys.state & (STATE_CYCLE | STATE_HOMING)){\n    // Initialize stepper output bits\n    st.dir_outbits = dir_port_invert_mask; \n    st.step_outbits = step_port_invert_mask;\n    \n    // Initialize step pulse timing from settings. Here to ensure updating after re-writing.\n    #ifdef STEP_PULSE_DELAY\n      // Set total step pulse time after direction pin set. Ad hoc computation from oscilloscope.\n      st.step_pulse_time = -(((settings.pulse_microseconds+STEP_PULSE_DELAY-2)*TICKS_PER_MICROSECOND) >> 3);\n      // Set delay between direction pin write and step command.\n      OCR0A = -(((settings.pulse_microseconds)*TICKS_PER_MICROSECOND) >> 3);\n    #else // Normal operation\n      // Set step pulse time. Ad hoc computation from oscilloscope. Uses two's complement.\n      st.step_pulse_time = -(((settings.pulse_microseconds-2)*TICKS_PER_MICROSECOND) >> 3);\n    #endif\n\n    // Enable Stepper Driver Interrupt\n    TIMSK1 |= (1<<OCIE1A);\n  }\n}\n\n\n// Stepper shutdown\nvoid st_go_idle() \n{\n  // Disable Stepper Driver Interrupt. Allow Stepper Port Reset Interrupt to finish, if active.\n  TIMSK1 &= ~(1<<OCIE1A); // Disable Timer1 interrupt\n  TCCR1B = (TCCR1B & ~((1<<CS12) | (1<<CS11))) | (1<<CS10); // Reset clock to no prescaling.\n  busy = false;\n  \n  // Set stepper driver idle state, disabled or enabled, depending on settings and circumstances.\n  bool pin_state = false; // Keep enabled.\n  if (((settings.stepper_idle_lock_time != 0xff) || sys.rt_exec_alarm) && sys.state != STATE_HOMING) {\n    // Force stepper dwell to lock axes for a defined amount of time to ensure the axes come to a complete\n    // stop and not drift from residual inertial forces at the end of the last movement.\n    delay_ms(settings.stepper_idle_lock_time);\n    pin_state = true; // Override. Disable steppers.\n  }\n  if (bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)) { pin_state = !pin_state; } // Apply pin invert.\n  if (pin_state) { STEPPERS_DISABLE_PORT |= (1<<STEPPERS_DISABLE_BIT); }\n  else { STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT); }\n}\n\n\n/* \"The Stepper Driver Interrupt\" - This timer interrupt is the workhorse of Grbl. Grbl employs\n   the venerable Bresenham line algorithm to manage and exactly synchronize multi-axis moves.\n   Unlike the popular DDA algorithm, the Bresenham algorithm is not susceptible to numerical\n   round-off errors and only requires fast integer counters, meaning low computational overhead\n   and maximizing the Arduino's capabilities. However, the downside of the Bresenham algorithm\n   is, for certain multi-axis motions, the non-dominant axes may suffer from un-smooth step \n   pulse trains, or aliasing, which can lead to strange audible noises or shaking. This is \n   particularly noticeable or may cause motion issues at low step frequencies (0-5kHz), but \n   is usually not a physical problem at higher frequencies, although audible.\n     To improve Bresenham multi-axis performance, Grbl uses what we call an Adaptive Multi-Axis\n   Step Smoothing (AMASS) algorithm, which does what the name implies. At lower step frequencies,\n   AMASS artificially increases the Bresenham resolution without effecting the algorithm's \n   innate exactness. AMASS adapts its resolution levels automatically depending on the step\n   frequency to be executed, meaning that for even lower step frequencies the step smoothing \n   level increases. Algorithmically, AMASS is acheived by a simple bit-shifting of the Bresenham\n   step count for each AMASS level. For example, for a Level 1 step smoothing, we bit shift \n   the Bresenham step event count, effectively multiplying it by 2, while the axis step counts \n   remain the same, and then double the stepper ISR frequency. In effect, we are allowing the\n   non-dominant Bresenham axes step in the intermediate ISR tick, while the dominant axis is \n   stepping every two ISR ticks, rather than every ISR tick in the traditional sense. At AMASS\n   Level 2, we simply bit-shift again, so the non-dominant Bresenham axes can step within any \n   of the four ISR ticks, the dominant axis steps every four ISR ticks, and quadruple the \n   stepper ISR frequency. And so on. This, in effect, virtually eliminates multi-axis aliasing \n   issues with the Bresenham algorithm and does not significantly alter Grbl's performance, but \n   in fact, more efficiently utilizes unused CPU cycles overall throughout all configurations.\n     AMASS retains the Bresenham algorithm exactness by requiring that it always executes a full\n   Bresenham step, regardless of AMASS Level. Meaning that for an AMASS Level 2, all four \n   intermediate steps must be completed such that baseline Bresenham (Level 0) count is always \n   retained. Similarly, AMASS Level 3 means all eight intermediate steps must be executed. \n   Although the AMASS Levels are in reality arbitrary, where the baseline Bresenham counts can\n   be multiplied by any integer value, multiplication by powers of two are simply used to ease \n   CPU overhead with bitshift integer operations. \n     This interrupt is simple and dumb by design. All the computational heavy-lifting, as in\n   determining accelerations, is performed elsewhere. This interrupt pops pre-computed segments,\n   defined as constant velocity over n number of steps, from the step segment buffer and then \n   executes them by pulsing the stepper pins appropriately via the Bresenham algorithm. This \n   ISR is supported by The Stepper Port Reset Interrupt which it uses to reset the stepper port\n   after each pulse. The bresenham line tracer algorithm controls all stepper outputs\n   simultaneously with these two interrupts.\n   \n   NOTE: This interrupt must be as efficient as possible and complete before the next ISR tick, \n   which for Grbl must be less than 33.3usec (@30kHz ISR rate). Oscilloscope measured time in \n   ISR is 5usec typical and 25usec maximum, well below requirement.\n   NOTE: This ISR expects at least one step to be executed per segment.\n*/\n// TODO: Replace direct updating of the int32 position counters in the ISR somehow. Perhaps use smaller\n// int8 variables and update position counters only when a segment completes. This can get complicated \n// with probing and homing cycles that require true real-time positions.\nISR(TIMER1_COMPA_vect)\n{        \n// SPINDLE_ENABLE_PORT ^= 1<<SPINDLE_ENABLE_BIT; // Debug: Used to time ISR\n  if (busy) { return; } // The busy-flag is used to avoid reentering this interrupt\n  \n  // Set the direction pins a couple of nanoseconds before we step the steppers\n  DIRECTION_PORT = (DIRECTION_PORT & ~DIRECTION_MASK) | (st.dir_outbits & DIRECTION_MASK);\n\n  // Then pulse the stepping pins\n  #ifdef STEP_PULSE_DELAY\n    st.step_bits = (STEP_PORT & ~STEP_MASK) | st.step_outbits; // Store out_bits to prevent overwriting.\n  #else  // Normal operation\n    STEP_PORT = (STEP_PORT & ~STEP_MASK) | st.step_outbits;\n  #endif  \n\n  // Enable step pulse reset timer so that The Stepper Port Reset Interrupt can reset the signal after\n  // exactly settings.pulse_microseconds microseconds, independent of the main Timer1 prescaler.\n  TCNT0 = st.step_pulse_time; // Reload Timer0 counter\n  TCCR0B = (1<<CS01); // Begin Timer0. Full speed, 1/8 prescaler\n\n  busy = true;\n  sei(); // Re-enable interrupts to allow Stepper Port Reset Interrupt to fire on-time. \n         // NOTE: The remaining code in this ISR will finish before returning to main program.\n    \n  // If there is no step segment, attempt to pop one from the stepper buffer\n  if (st.exec_segment == NULL) {\n    // Anything in the buffer? If so, load and initialize next step segment.\n    if (segment_buffer_head != segment_buffer_tail) {\n      // Initialize new step segment and load number of steps to execute\n      st.exec_segment = &segment_buffer[segment_buffer_tail];\n\n      #ifndef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING\n        // With AMASS is disabled, set timer prescaler for segments with slow step frequencies (< 250Hz).\n        TCCR1B = (TCCR1B & ~(0x07<<CS10)) | (st.exec_segment->prescaler<<CS10);\n      #endif\n\n      // Initialize step segment timing per step and load number of steps to execute.\n      OCR1A = st.exec_segment->cycles_per_tick;\n      st.step_count = st.exec_segment->n_step; // NOTE: Can sometimes be zero when moving slow.\n      // If the new segment starts a new planner block, initialize stepper variables and counters.\n      // NOTE: When the segment data index changes, this indicates a new planner block.\n      if ( st.exec_block_index != st.exec_segment->st_block_index ) {\n        st.exec_block_index = st.exec_segment->st_block_index;\n        st.exec_block = &st_block_buffer[st.exec_block_index];\n        \n        // Initialize Bresenham line and distance counters\n        st.counter_x = st.counter_y = st.counter_z = (st.exec_block->step_event_count >> 1);\n      }\n      st.dir_outbits = st.exec_block->direction_bits ^ dir_port_invert_mask; \n\n      #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING\n        // With AMASS enabled, adjust Bresenham axis increment counters according to AMASS level.\n        st.steps[X_AXIS] = st.exec_block->steps[X_AXIS] >> st.exec_segment->amass_level;\n        st.steps[Y_AXIS] = st.exec_block->steps[Y_AXIS] >> st.exec_segment->amass_level;\n        st.steps[Z_AXIS] = st.exec_block->steps[Z_AXIS] >> st.exec_segment->amass_level;\n      #endif\n      \n    } else {\n      // Segment buffer empty. Shutdown.\n      st_go_idle();\n      bit_true_atomic(sys.rt_exec_state,EXEC_CYCLE_STOP); // Flag main program for cycle end\n      return; // Nothing to do but exit.\n    }  \n  }\n  \n  \n  // Check probing state.\n  probe_state_monitor();\n   \n  // Reset step out bits.\n  st.step_outbits = 0; \n\n  // Execute step displacement profile by Bresenham line algorithm\n  #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING\n    st.counter_x += st.steps[X_AXIS];\n  #else\n    st.counter_x += st.exec_block->steps[X_AXIS];\n  #endif  \n  if (st.counter_x > st.exec_block->step_event_count) {\n    st.step_outbits |= (1<<X_STEP_BIT);\n    st.counter_x -= st.exec_block->step_event_count;\n    if (st.exec_block->direction_bits & (1<<X_DIRECTION_BIT)) { sys.position[X_AXIS]--; }\n    else { sys.position[X_AXIS]++; }\n  }\n  #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING\n    st.counter_y += st.steps[Y_AXIS];\n  #else\n    st.counter_y += st.exec_block->steps[Y_AXIS];\n  #endif    \n  if (st.counter_y > st.exec_block->step_event_count) {\n    st.step_outbits |= (1<<Y_STEP_BIT);\n    st.counter_y -= st.exec_block->step_event_count;\n    if (st.exec_block->direction_bits & (1<<Y_DIRECTION_BIT)) { sys.position[Y_AXIS]--; }\n    else { sys.position[Y_AXIS]++; }\n  }\n  #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING\n    st.counter_z += st.steps[Z_AXIS];\n  #else\n    st.counter_z += st.exec_block->steps[Z_AXIS];\n  #endif  \n  if (st.counter_z > st.exec_block->step_event_count) {\n    st.step_outbits |= (1<<Z_STEP_BIT);\n    st.counter_z -= st.exec_block->step_event_count;\n    if (st.exec_block->direction_bits & (1<<Z_DIRECTION_BIT)) { sys.position[Z_AXIS]--; }\n    else { sys.position[Z_AXIS]++; }\n  }  \n\n  // During a homing cycle, lock out and prevent desired axes from moving.\n  if (sys.state == STATE_HOMING) { st.step_outbits &= sys.homing_axis_lock; }   \n\n  st.step_count--; // Decrement step events count \n  if (st.step_count == 0) {\n    // Segment is complete. Discard current segment and advance segment indexing.\n    st.exec_segment = NULL;\n    if ( ++segment_buffer_tail == SEGMENT_BUFFER_SIZE) { segment_buffer_tail = 0; }\n  }\n\n  st.step_outbits ^= step_port_invert_mask;  // Apply step port invert mask    \n  busy = false;\n// SPINDLE_ENABLE_PORT ^= 1<<SPINDLE_ENABLE_BIT; // Debug: Used to time ISR\n}\n\n\n/* The Stepper Port Reset Interrupt: Timer0 OVF interrupt handles the falling edge of the step\n   pulse. This should always trigger before the next Timer1 COMPA interrupt and independently\n   finish, if Timer1 is disabled after completing a move.\n   NOTE: Interrupt collisions between the serial and stepper interrupts can cause delays by\n   a few microseconds, if they execute right before one another. Not a big deal, but can\n   cause issues at high step rates if another high frequency asynchronous interrupt is \n   added to Grbl.\n*/\n// This interrupt is enabled by ISR_TIMER1_COMPAREA when it sets the motor port bits to execute\n// a step. This ISR resets the motor port after a short period (settings.pulse_microseconds) \n// completing one step cycle.\nISR(TIMER0_OVF_vect)\n{\n  // Reset stepping pins (leave the direction pins)\n  STEP_PORT = (STEP_PORT & ~STEP_MASK) | (step_port_invert_mask & STEP_MASK); \n  TCCR0B = 0; // Disable Timer0 to prevent re-entering this interrupt when it's not needed. \n}\n#ifdef STEP_PULSE_DELAY\n  // This interrupt is used only when STEP_PULSE_DELAY is enabled. Here, the step pulse is\n  // initiated after the STEP_PULSE_DELAY time period has elapsed. The ISR TIMER2_OVF interrupt\n  // will then trigger after the appropriate settings.pulse_microseconds, as in normal operation.\n  // The new timing between direction, step pulse, and step complete events are setup in the\n  // st_wake_up() routine.\n  ISR(TIMER0_COMPA_vect) \n  { \n    STEP_PORT = st.step_bits; // Begin step pulse.\n  }\n#endif\n\n\n// Generates the step and direction port invert masks used in the Stepper Interrupt Driver.\nvoid st_generate_step_dir_invert_masks()\n{  \n  uint8_t idx;\n  step_port_invert_mask = 0;\n  dir_port_invert_mask = 0;\n  for (idx=0; idx<N_AXIS; idx++) {\n    if (bit_istrue(settings.step_invert_mask,bit(idx))) { step_port_invert_mask |= get_step_pin_mask(idx); }\n    if (bit_istrue(settings.dir_invert_mask,bit(idx))) { dir_port_invert_mask |= get_direction_pin_mask(idx); }\n  }\n}\n\n\n// Reset and clear stepper subsystem variables\nvoid st_reset()\n{\n  // Initialize stepper driver idle state.\n  st_go_idle();\n  \n  // Initialize stepper algorithm variables.\n  memset(&prep, 0, sizeof(prep));\n  memset(&st, 0, sizeof(st));\n  st.exec_segment = NULL;\n  pl_block = NULL;  // Planner block pointer used by segment buffer\n  segment_buffer_tail = 0;\n  segment_buffer_head = 0; // empty = tail\n  segment_next_head = 1;\n  busy = false;\n  \n  st_generate_step_dir_invert_masks();\n      \n  // Initialize step and direction port pins.\n  STEP_PORT = (STEP_PORT & ~STEP_MASK) | step_port_invert_mask;\n  DIRECTION_PORT = (DIRECTION_PORT & ~DIRECTION_MASK) | dir_port_invert_mask;\n}\n\n\n// Initialize and start the stepper motor subsystem\nvoid stepper_init()\n{\n  // Configure step and direction interface pins\n  STEP_DDR |= STEP_MASK;\n  STEPPERS_DISABLE_DDR |= 1<<STEPPERS_DISABLE_BIT;\n  DIRECTION_DDR |= DIRECTION_MASK;\n\n  // Configure Timer 1: Stepper Driver Interrupt\n  TCCR1B &= ~(1<<WGM13); // waveform generation = 0100 = CTC\n  TCCR1B |=  (1<<WGM12);\n  TCCR1A &= ~((1<<WGM11) | (1<<WGM10)); \n  TCCR1A &= ~((1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0)); // Disconnect OC1 output\n  // TCCR1B = (TCCR1B & ~((1<<CS12) | (1<<CS11))) | (1<<CS10); // Set in st_go_idle().\n  // TIMSK1 &= ~(1<<OCIE1A);  // Set in st_go_idle().\n  \n  // Configure Timer 0: Stepper Port Reset Interrupt\n  TIMSK0 &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0)); // Disconnect OC0 outputs and OVF interrupt.\n  TCCR0A = 0; // Normal operation\n  TCCR0B = 0; // Disable Timer0 until needed\n  TIMSK0 |= (1<<TOIE0); // Enable Timer0 overflow interrupt\n  #ifdef STEP_PULSE_DELAY\n    TIMSK0 |= (1<<OCIE0A); // Enable Timer0 Compare Match A interrupt\n  #endif\n}\n  \n\n// Called by planner_recalculate() when the executing block is updated by the new plan.\nvoid st_update_plan_block_parameters()\n{ \n  if (pl_block != NULL) { // Ignore if at start of a new block.\n    prep.flag_partial_block = true;\n    pl_block->entry_speed_sqr = prep.current_speed*prep.current_speed; // Update entry speed.\n    pl_block = NULL; // Flag st_prep_segment() to load new velocity profile.\n  }\n}\n\n\n/* Prepares step segment buffer. Continuously called from main program. \n\n   The segment buffer is an intermediary buffer interface between the execution of steps\n   by the stepper algorithm and the velocity profiles generated by the planner. The stepper\n   algorithm only executes steps within the segment buffer and is filled by the main program\n   when steps are \"checked-out\" from the first block in the planner buffer. This keeps the\n   step execution and planning optimization processes atomic and protected from each other.\n   The number of steps \"checked-out\" from the planner buffer and the number of segments in\n   the segment buffer is sized and computed such that no operation in the main program takes\n   longer than the time it takes the stepper algorithm to empty it before refilling it. \n   Currently, the segment buffer conservatively holds roughly up to 40-50 msec of steps.\n   NOTE: Computation units are in steps, millimeters, and minutes.\n*/\nvoid st_prep_buffer()\n{\n\n  if (sys.state & (STATE_HOLD|STATE_MOTION_CANCEL|STATE_SAFETY_DOOR)) { \n    // Check if we still need to generate more segments for a motion suspend.\n    if (prep.current_speed == 0.0) { return; } // Nothing to do. Bail.\n  }\n  \n  while (segment_buffer_tail != segment_next_head) { // Check if we need to fill the buffer.\n\n    // Determine if we need to load a new planner block or if the block has been replanned. \n    if (pl_block == NULL) {\n      pl_block = plan_get_current_block(); // Query planner for a queued block\n      if (pl_block == NULL) { return; } // No planner blocks. Exit.\n                      \n      // Check if the segment buffer completed the last planner block. If so, load the Bresenham\n      // data for the block. If not, we are still mid-block and the velocity profile was updated. \n      if (prep.flag_partial_block) {\n        prep.flag_partial_block = false; // Reset flag\n      } else {\n        // Increment stepper common data index to store new planner block data. \n        if ( ++prep.st_block_index == (SEGMENT_BUFFER_SIZE-1) ) { prep.st_block_index = 0; }\n        \n        // Prepare and copy Bresenham algorithm segment data from the new planner block, so that\n        // when the segment buffer completes the planner block, it may be discarded when the \n        // segment buffer finishes the prepped block, but the stepper ISR is still executing it. \n        st_prep_block = &st_block_buffer[prep.st_block_index];\n        st_prep_block->direction_bits = pl_block->direction_bits;\n        #ifndef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING\n          st_prep_block->steps[X_AXIS] = pl_block->steps[X_AXIS];\n          st_prep_block->steps[Y_AXIS] = pl_block->steps[Y_AXIS];\n          st_prep_block->steps[Z_AXIS] = pl_block->steps[Z_AXIS];\n          st_prep_block->step_event_count = pl_block->step_event_count;\n        #else\n          // With AMASS enabled, simply bit-shift multiply all Bresenham data by the max AMASS \n          // level, such that we never divide beyond the original data anywhere in the algorithm.\n          // If the original data is divided, we can lose a step from integer roundoff.\n          st_prep_block->steps[X_AXIS] = pl_block->steps[X_AXIS] << MAX_AMASS_LEVEL;\n          st_prep_block->steps[Y_AXIS] = pl_block->steps[Y_AXIS] << MAX_AMASS_LEVEL;\n          st_prep_block->steps[Z_AXIS] = pl_block->steps[Z_AXIS] << MAX_AMASS_LEVEL;\n          st_prep_block->step_event_count = pl_block->step_event_count << MAX_AMASS_LEVEL;\n        #endif\n        \n        // Initialize segment buffer data for generating the segments.\n        prep.steps_remaining = pl_block->step_event_count;\n        prep.step_per_mm = prep.steps_remaining/pl_block->millimeters;\n        prep.req_mm_increment = REQ_MM_INCREMENT_SCALAR/prep.step_per_mm;\n        \n        prep.dt_remainder = 0.0; // Reset for new planner block\n\n        if (sys.state & (STATE_HOLD|STATE_MOTION_CANCEL|STATE_SAFETY_DOOR)) {\n          // Override planner block entry speed and enforce deceleration during feed hold.\n          prep.current_speed = prep.exit_speed; \n          pl_block->entry_speed_sqr = prep.exit_speed*prep.exit_speed; \n        }\n        else { prep.current_speed = sqrt(pl_block->entry_speed_sqr); }\n      }\n     \n      /* --------------------------------------------------------------------------------- \n         Compute the velocity profile of a new planner block based on its entry and exit\n         speeds, or recompute the profile of a partially-completed planner block if the \n         planner has updated it. For a commanded forced-deceleration, such as from a feed \n         hold, override the planner velocities and decelerate to the target exit speed.\n      */\n      prep.mm_complete = 0.0; // Default velocity profile complete at 0.0mm from end of block.\n      float inv_2_accel = 0.5/pl_block->acceleration;\n      if (sys.state & (STATE_HOLD|STATE_MOTION_CANCEL|STATE_SAFETY_DOOR)) { // [Forced Deceleration to Zero Velocity]\n        // Compute velocity profile parameters for a feed hold in-progress. This profile overrides\n        // the planner block profile, enforcing a deceleration to zero speed.\n        prep.ramp_type = RAMP_DECEL;\n        // Compute decelerate distance relative to end of block.\n        float decel_dist = pl_block->millimeters - inv_2_accel*pl_block->entry_speed_sqr;\n        if (decel_dist < 0.0) {\n          // Deceleration through entire planner block. End of feed hold is not in this block.\n          prep.exit_speed = sqrt(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters);\n        } else {\n          prep.mm_complete = decel_dist; // End of feed hold.\n          prep.exit_speed = 0.0;\n        }\n      } else { // [Normal Operation]\n        // Compute or recompute velocity profile parameters of the prepped planner block.\n        prep.ramp_type = RAMP_ACCEL; // Initialize as acceleration ramp.\n        prep.accelerate_until = pl_block->millimeters; \n        prep.exit_speed = plan_get_exec_block_exit_speed();   \n        float exit_speed_sqr = prep.exit_speed*prep.exit_speed;\n        float intersect_distance =\n                0.5*(pl_block->millimeters+inv_2_accel*(pl_block->entry_speed_sqr-exit_speed_sqr));\n        if (intersect_distance > 0.0) {\n          if (intersect_distance < pl_block->millimeters) { // Either trapezoid or triangle types\n            // NOTE: For acceleration-cruise and cruise-only types, following calculation will be 0.0.\n            prep.decelerate_after = inv_2_accel*(pl_block->nominal_speed_sqr-exit_speed_sqr);\n            if (prep.decelerate_after < intersect_distance) { // Trapezoid type\n              prep.maximum_speed = sqrt(pl_block->nominal_speed_sqr);\n              if (pl_block->entry_speed_sqr == pl_block->nominal_speed_sqr) { \n                // Cruise-deceleration or cruise-only type.\n                prep.ramp_type = RAMP_CRUISE;\n              } else {\n                // Full-trapezoid or acceleration-cruise types\n                prep.accelerate_until -= inv_2_accel*(pl_block->nominal_speed_sqr-pl_block->entry_speed_sqr); \n              }\n            } else { // Triangle type\n              prep.accelerate_until = intersect_distance;\n              prep.decelerate_after = intersect_distance;\n              prep.maximum_speed = sqrt(2.0*pl_block->acceleration*intersect_distance+exit_speed_sqr);\n            }          \n          } else { // Deceleration-only type\n            prep.ramp_type = RAMP_DECEL;\n            // prep.decelerate_after = pl_block->millimeters;\n            prep.maximum_speed = prep.current_speed;\n          }\n        } else { // Acceleration-only type\n          prep.accelerate_until = 0.0;\n          // prep.decelerate_after = 0.0;\n          prep.maximum_speed = prep.exit_speed;\n        }\n      }  \n    }\n\n    // Initialize new segment\n    segment_t *prep_segment = &segment_buffer[segment_buffer_head];\n\n    // Set new segment to point to the current segment data block.\n    prep_segment->st_block_index = prep.st_block_index;\n\n    /*------------------------------------------------------------------------------------\n        Compute the average velocity of this new segment by determining the total distance\n      traveled over the segment time DT_SEGMENT. The following code first attempts to create \n      a full segment based on the current ramp conditions. If the segment time is incomplete \n      when terminating at a ramp state change, the code will continue to loop through the\n      progressing ramp states to fill the remaining segment execution time. However, if \n      an incomplete segment terminates at the end of the velocity profile, the segment is \n      considered completed despite having a truncated execution time less than DT_SEGMENT.\n        The velocity profile is always assumed to progress through the ramp sequence:\n      acceleration ramp, cruising state, and deceleration ramp. Each ramp's travel distance\n      may range from zero to the length of the block. Velocity profiles can end either at \n      the end of planner block (typical) or mid-block at the end of a forced deceleration, \n      such as from a feed hold.\n    */\n    float dt_max = DT_SEGMENT; // Maximum segment time\n    float dt = 0.0; // Initialize segment time\n    float time_var = dt_max; // Time worker variable\n    float mm_var; // mm-Distance worker variable\n    float speed_var; // Speed worker variable   \n    float mm_remaining = pl_block->millimeters; // New segment distance from end of block.\n    float minimum_mm = mm_remaining-prep.req_mm_increment; // Guarantee at least one step.\n    if (minimum_mm < 0.0) { minimum_mm = 0.0; }\n\n    do {\n      switch (prep.ramp_type) {\n        case RAMP_ACCEL: \n          // NOTE: Acceleration ramp only computes during first do-while loop.\n          speed_var = pl_block->acceleration*time_var;\n          mm_remaining -= time_var*(prep.current_speed + 0.5*speed_var);\n          if (mm_remaining < prep.accelerate_until) { // End of acceleration ramp.\n            // Acceleration-cruise, acceleration-deceleration ramp junction, or end of block.\n            mm_remaining = prep.accelerate_until; // NOTE: 0.0 at EOB\n            time_var = 2.0*(pl_block->millimeters-mm_remaining)/(prep.current_speed+prep.maximum_speed);\n            if (mm_remaining == prep.decelerate_after) { prep.ramp_type = RAMP_DECEL; }\n            else { prep.ramp_type = RAMP_CRUISE; }\n            prep.current_speed = prep.maximum_speed;\n          } else { // Acceleration only. \n            prep.current_speed += speed_var;\n          }\n          break;\n        case RAMP_CRUISE: \n          // NOTE: mm_var used to retain the last mm_remaining for incomplete segment time_var calculations.\n          // NOTE: If maximum_speed*time_var value is too low, round-off can cause mm_var to not change. To \n          //   prevent this, simply enforce a minimum speed threshold in the planner.\n          mm_var = mm_remaining - prep.maximum_speed*time_var;\n          if (mm_var < prep.decelerate_after) { // End of cruise. \n            // Cruise-deceleration junction or end of block.\n            time_var = (mm_remaining - prep.decelerate_after)/prep.maximum_speed;\n            mm_remaining = prep.decelerate_after; // NOTE: 0.0 at EOB\n            prep.ramp_type = RAMP_DECEL;\n          } else { // Cruising only.         \n            mm_remaining = mm_var; \n          } \n          break;\n        default: // case RAMP_DECEL:\n          // NOTE: mm_var used as a misc worker variable to prevent errors when near zero speed.\n          speed_var = pl_block->acceleration*time_var; // Used as delta speed (mm/min)\n          if (prep.current_speed > speed_var) { // Check if at or below zero speed.\n            // Compute distance from end of segment to end of block.\n            mm_var = mm_remaining - time_var*(prep.current_speed - 0.5*speed_var); // (mm)\n            if (mm_var > prep.mm_complete) { // Deceleration only.\n              mm_remaining = mm_var;\n              prep.current_speed -= speed_var;\n              break; // Segment complete. Exit switch-case statement. Continue do-while loop.\n            }\n          } // End of block or end of forced-deceleration.\n          time_var = 2.0*(mm_remaining-prep.mm_complete)/(prep.current_speed+prep.exit_speed);\n          mm_remaining = prep.mm_complete; \n      }\n      dt += time_var; // Add computed ramp time to total segment time.\n      if (dt < dt_max) { time_var = dt_max - dt; } // **Incomplete** At ramp junction.\n      else {\n        if (mm_remaining > minimum_mm) { // Check for very slow segments with zero steps.\n          // Increase segment time to ensure at least one step in segment. Override and loop\n          // through distance calculations until minimum_mm or mm_complete.\n          dt_max += DT_SEGMENT;\n          time_var = dt_max - dt;\n        } else { \n          break; // **Complete** Exit loop. Segment execution time maxed.\n        }\n      }\n    } while (mm_remaining > prep.mm_complete); // **Complete** Exit loop. Profile complete.\n\n   \n    /* -----------------------------------------------------------------------------------\n       Compute segment step rate, steps to execute, and apply necessary rate corrections.\n       NOTE: Steps are computed by direct scalar conversion of the millimeter distance \n       remaining in the block, rather than incrementally tallying the steps executed per\n       segment. This helps in removing floating point round-off issues of several additions. \n       However, since floats have only 7.2 significant digits, long moves with extremely \n       high step counts can exceed the precision of floats, which can lead to lost steps.\n       Fortunately, this scenario is highly unlikely and unrealistic in CNC machines\n       supported by Grbl (i.e. exceeding 10 meters axis travel at 200 step/mm).\n    */\n    float steps_remaining = prep.step_per_mm*mm_remaining; // Convert mm_remaining to steps\n    float n_steps_remaining = ceil(steps_remaining); // Round-up current steps remaining\n    float last_n_steps_remaining = ceil(prep.steps_remaining); // Round-up last steps remaining\n    prep_segment->n_step = last_n_steps_remaining-n_steps_remaining; // Compute number of steps to execute.\n    \n    // Bail if we are at the end of a feed hold and don't have a step to execute.\n    if (prep_segment->n_step == 0) {\n      if (sys.state & (STATE_HOLD|STATE_MOTION_CANCEL|STATE_SAFETY_DOOR)) {\n        // Less than one step to decelerate to zero speed, but already very close. AMASS \n        // requires full steps to execute. So, just bail.\n        prep.current_speed = 0.0; // NOTE: (=0.0) Used to indicate completed segment calcs for hold.\n        prep.dt_remainder = 0.0;\n        prep.steps_remaining = n_steps_remaining;\n        pl_block->millimeters = prep.steps_remaining/prep.step_per_mm; // Update with full steps.\n        plan_cycle_reinitialize();         \n        return; // Segment not generated, but current step data still retained.\n      }\n    }\n\n    // Compute segment step rate. Since steps are integers and mm distances traveled are not,\n    // the end of every segment can have a partial step of varying magnitudes that are not \n    // executed, because the stepper ISR requires whole steps due to the AMASS algorithm. To\n    // compensate, we track the time to execute the previous segment's partial step and simply\n    // apply it with the partial step distance to the current segment, so that it minutely\n    // adjusts the whole segment rate to keep step output exact. These rate adjustments are \n    // typically very small and do not adversely effect performance, but ensures that Grbl\n    // outputs the exact acceleration and velocity profiles as computed by the planner.\n    dt += prep.dt_remainder; // Apply previous segment partial step execute time\n    float inv_rate = dt/(last_n_steps_remaining - steps_remaining); // Compute adjusted step rate inverse\n    prep.dt_remainder = (n_steps_remaining - steps_remaining)*inv_rate; // Update segment partial step time\n\n    // Compute CPU cycles per step for the prepped segment.\n    uint32_t cycles = ceil( (TICKS_PER_MICROSECOND*1000000*60)*inv_rate ); // (cycles/step)    \n\n    #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING        \n      // Compute step timing and multi-axis smoothing level.\n      // NOTE: AMASS overdrives the timer with each level, so only one prescalar is required.\n      if (cycles < AMASS_LEVEL1) { prep_segment->amass_level = 0; }\n      else {\n        if (cycles < AMASS_LEVEL2) { prep_segment->amass_level = 1; }\n        else if (cycles < AMASS_LEVEL3) { prep_segment->amass_level = 2; }\n        else { prep_segment->amass_level = 3; }    \n        cycles >>= prep_segment->amass_level; \n        prep_segment->n_step <<= prep_segment->amass_level;\n      }\n      if (cycles < (1UL << 16)) { prep_segment->cycles_per_tick = cycles; } // < 65536 (4.1ms @ 16MHz)\n      else { prep_segment->cycles_per_tick = 0xffff; } // Just set the slowest speed possible.\n    #else \n      // Compute step timing and timer prescalar for normal step generation.\n      if (cycles < (1UL << 16)) { // < 65536  (4.1ms @ 16MHz)\n        prep_segment->prescaler = 1; // prescaler: 0\n        prep_segment->cycles_per_tick = cycles;\n      } else if (cycles < (1UL << 19)) { // < 524288 (32.8ms@16MHz)\n        prep_segment->prescaler = 2; // prescaler: 8\n        prep_segment->cycles_per_tick = cycles >> 3;\n      } else { \n        prep_segment->prescaler = 3; // prescaler: 64\n        if (cycles < (1UL << 22)) { // < 4194304 (262ms@16MHz)\n          prep_segment->cycles_per_tick =  cycles >> 6;\n        } else { // Just set the slowest speed possible. (Around 4 step/sec.)\n          prep_segment->cycles_per_tick = 0xffff;\n        }\n      }\n    #endif\n\n    // Segment complete! Increment segment buffer indices.\n    segment_buffer_head = segment_next_head;\n    if ( ++segment_next_head == SEGMENT_BUFFER_SIZE ) { segment_next_head = 0; }\n\n    // Setup initial conditions for next segment.\n    if (mm_remaining > prep.mm_complete) { \n      // Normal operation. Block incomplete. Distance remaining in block to be executed.\n      pl_block->millimeters = mm_remaining;      \n      prep.steps_remaining = steps_remaining;  \n    } else { \n      // End of planner block or forced-termination. No more distance to be executed.\n      if (mm_remaining > 0.0) { // At end of forced-termination.\n        // Reset prep parameters for resuming and then bail. Allow the stepper ISR to complete\n        // the segment queue, where realtime protocol will set new state upon receiving the \n        // cycle stop flag from the ISR. Prep_segment is blocked until then.\n        prep.current_speed = 0.0; // NOTE: (=0.0) Used to indicate completed segment calcs for hold.\n        prep.dt_remainder = 0.0;\n        prep.steps_remaining = ceil(steps_remaining);\n        pl_block->millimeters = prep.steps_remaining/prep.step_per_mm; // Update with full steps.\n        plan_cycle_reinitialize(); \n        return; // Bail!\n      } else { // End of planner block\n        // The planner block is complete. All steps are set to be executed in the segment buffer.\n        pl_block = NULL; // Set pointer to indicate check and load next planner block.\n        plan_discard_current_block();\n      }\n    }\n\n  } \n}      \n\n\n// Called by realtime status reporting to fetch the current speed being executed. This value\n// however is not exactly the current speed, but the speed computed in the last step segment\n// in the segment buffer. It will always be behind by up to the number of segment blocks (-1)\n// divided by the ACCELERATION TICKS PER SECOND in seconds. \n#ifdef REPORT_REALTIME_RATE\n  float st_get_realtime_rate()\n  {\n     if (sys.state & (STATE_CYCLE | STATE_HOMING | STATE_HOLD | STATE_MOTION_CANCEL | STATE_SAFETY_DOOR)){\n       return prep.current_speed;\n     }\n    return 0.0f;\n  }\n#endif\n"
  },
  {
    "path": "stepper.h",
    "content": "/*\n  stepper.h - stepper motor driver: executes motion plans of planner.c using the stepper motors\n  Part of Grbl\n\n  Copyright (c) 2011-2015 Sungeun K. Jeon\n  Copyright (c) 2009-2011 Simen Svale Skogsrud\n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef stepper_h\n#define stepper_h \n\n#ifndef SEGMENT_BUFFER_SIZE\n  #define SEGMENT_BUFFER_SIZE 6\n#endif\n\n// Initialize and setup the stepper motor subsystem\nvoid stepper_init();\n\n// Enable steppers, but cycle does not start unless called by motion control or realtime command.\nvoid st_wake_up();\n\n// Immediately disables steppers\nvoid st_go_idle();\n\n// Generate the step and direction port invert masks.\nvoid st_generate_step_dir_invert_masks();\n\n// Reset the stepper subsystem variables       \nvoid st_reset();\n             \n// Reloads step segment buffer. Called continuously by realtime execution system.\nvoid st_prep_buffer();\n\n// Called by planner_recalculate() when the executing block is updated by the new plan.\nvoid st_update_plan_block_parameters();\n\n// Called by realtime status reporting if realtime rate reporting is enabled in config.h.\n#ifdef REPORT_REALTIME_RATE\nfloat st_get_realtime_rate();\n#endif\n\n#endif\n"
  },
  {
    "path": "system.c",
    "content": "/*\n  system.c - Handles system level commands and real-time processes\n  Part of Grbl\n\n  Copyright (c) 2014-2015 Sungeun K. Jeon  \n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include \"grbl.h\"\n\n\nvoid system_init() \n{\n  CONTROL_DDR &= ~(CONTROL_MASK); // Configure as input pins\n  #ifdef DISABLE_CONTROL_PIN_PULL_UP\n    CONTROL_PORT &= ~(CONTROL_MASK); // Normal low operation. Requires external pull-down.\n  #else\n    CONTROL_PORT |= CONTROL_MASK;   // Enable internal pull-up resistors. Normal high operation.\n  #endif\n  CONTROL_PCMSK |= CONTROL_MASK;  // Enable specific pins of the Pin Change Interrupt\n  PCICR |= (1 << CONTROL_INT);   // Enable Pin Change Interrupt\n}\n\n\n// Pin change interrupt for pin-out commands, i.e. cycle start, feed hold, and reset. Sets\n// only the realtime command execute variable to have the main program execute these when \n// its ready. This works exactly like the character-based realtime commands when picked off\n// directly from the incoming serial data stream.\nISR(CONTROL_INT_vect) \n{\n  uint8_t pin = (CONTROL_PIN & CONTROL_MASK);\n  #ifndef INVERT_CONTROL_PIN\n    pin ^= CONTROL_MASK;\n  #endif\n  // Enter only if any CONTROL pin is detected as active.\n  if (pin) { \n    if (bit_istrue(pin,bit(RESET_BIT))) {\n      mc_reset();\n    } else if (bit_istrue(pin,bit(CYCLE_START_BIT))) {\n      bit_true(sys.rt_exec_state, EXEC_CYCLE_START);\n    #ifndef ENABLE_SAFETY_DOOR_INPUT_PIN\n      } else if (bit_istrue(pin,bit(FEED_HOLD_BIT))) {\n        bit_true(sys.rt_exec_state, EXEC_FEED_HOLD); \n    #else\n      } else if (bit_istrue(pin,bit(SAFETY_DOOR_BIT))) {\n        bit_true(sys.rt_exec_state, EXEC_SAFETY_DOOR);\n    #endif\n    } \n  }\n}\n\n\n// Returns if safety door is ajar(T) or closed(F), based on pin state.\nuint8_t system_check_safety_door_ajar()\n{\n  #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN\n    #ifdef INVERT_CONTROL_PIN\n      return(bit_istrue(CONTROL_PIN,bit(SAFETY_DOOR_BIT)));\n    #else\n      return(bit_isfalse(CONTROL_PIN,bit(SAFETY_DOOR_BIT)));\n    #endif\n  #else\n    return(false); // Input pin not enabled, so just return that it's closed.\n  #endif\n}\n\n\n// Executes user startup script, if stored.\nvoid system_execute_startup(char *line) \n{\n  uint8_t n;\n  for (n=0; n < N_STARTUP_LINE; n++) {\n    if (!(settings_read_startup_line(n, line))) {\n      report_status_message(STATUS_SETTING_READ_FAIL);\n    } else {\n      if (line[0] != 0) {\n        printString(line); // Echo startup line to indicate execution.\n        report_status_message(gc_execute_line(line));\n      }\n    } \n  }  \n}\n\n\n// Directs and executes one line of formatted input from protocol_process. While mostly\n// incoming streaming g-code blocks, this also executes Grbl internal commands, such as \n// settings, initiating the homing cycle, and toggling switch states. This differs from\n// the realtime command module by being susceptible to when Grbl is ready to execute the \n// next line during a cycle, so for switches like block delete, the switch only effects\n// the lines that are processed afterward, not necessarily real-time during a cycle, \n// since there are motions already stored in the buffer. However, this 'lag' should not\n// be an issue, since these commands are not typically used during a cycle.\nuint8_t system_execute_line(char *line) \n{   \n  uint8_t char_counter = 1; \n  uint8_t helper_var = 0; // Helper variable\n  float parameter, value;\n  switch( line[char_counter] ) {\n    case 0 : report_grbl_help(); break;\n    case '$': case 'G': case 'C': case 'X':\n      if ( line[(char_counter+1)] != 0 ) { return(STATUS_INVALID_STATEMENT); }\n      switch( line[char_counter] ) {\n        case '$' : // Prints Grbl settings\n          if ( sys.state & (STATE_CYCLE | STATE_HOLD) ) { return(STATUS_IDLE_ERROR); } // Block during cycle. Takes too long to print.\n          else { report_grbl_settings(); }\n          break;\n        case 'G' : // Prints gcode parser state\n          // TODO: Move this to realtime commands for GUIs to request this data during suspend-state.\n          report_gcode_modes();\n          break;   \n        case 'C' : // Set check g-code mode [IDLE/CHECK]\n          // Perform reset when toggling off. Check g-code mode should only work if Grbl\n          // is idle and ready, regardless of alarm locks. This is mainly to keep things\n          // simple and consistent.\n          if ( sys.state == STATE_CHECK_MODE ) { \n            mc_reset(); \n            report_feedback_message(MESSAGE_DISABLED);\n          } else {\n            if (sys.state) { return(STATUS_IDLE_ERROR); } // Requires no alarm mode.\n            sys.state = STATE_CHECK_MODE;\n            report_feedback_message(MESSAGE_ENABLED);\n          }\n          break; \n        case 'X' : // Disable alarm lock [ALARM]\n          if (sys.state == STATE_ALARM) { \n            report_feedback_message(MESSAGE_ALARM_UNLOCK);\n            sys.state = STATE_IDLE;\n            // Don't run startup script. Prevents stored moves in startup from causing accidents.\n            if (system_check_safety_door_ajar()) { // Check safety door switch before returning.\n              bit_true(sys.rt_exec_state, EXEC_SAFETY_DOOR);\n              protocol_execute_realtime(); // Enter safety door mode.\n            }\n          } // Otherwise, no effect.\n          break;                   \n    //  case 'J' : break;  // Jogging methods\n          // TODO: Here jogging can be placed for execution as a seperate subprogram. It does not need to be \n          // susceptible to other realtime commands except for e-stop. The jogging function is intended to\n          // be a basic toggle on/off with controlled acceleration and deceleration to prevent skipped \n          // steps. The user would supply the desired feedrate, axis to move, and direction. Toggle on would\n          // start motion and toggle off would initiate a deceleration to stop. One could 'feather' the\n          // motion by repeatedly toggling to slow the motion to the desired location. Location data would \n          // need to be updated real-time and supplied to the user through status queries.\n          //   More controlled exact motions can be taken care of by inputting G0 or G1 commands, which are \n          // handled by the planner. It would be possible for the jog subprogram to insert blocks into the\n          // block buffer without having the planner plan them. It would need to manage de/ac-celerations \n          // on its own carefully. This approach could be effective and possibly size/memory efficient.  \n//       }\n//       break;\n      }\n      break;\n    default : \n      // Block any system command that requires the state as IDLE/ALARM. (i.e. EEPROM, homing)\n      if ( !(sys.state == STATE_IDLE || sys.state == STATE_ALARM) ) { return(STATUS_IDLE_ERROR); }\n      switch( line[char_counter] ) {\n        case '#' : // Print Grbl NGC parameters\n          if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); }\n          else { report_ngc_parameters(); }\n          break;          \n        case 'H' : // Perform homing cycle [IDLE/ALARM]\n          if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { \n            sys.state = STATE_HOMING; // Set system state variable\n            // Only perform homing if Grbl is idle or lost.\n            \n            // TODO: Likely not required.\n            if (system_check_safety_door_ajar()) { // Check safety door switch before homing.\n              bit_true(sys.rt_exec_state, EXEC_SAFETY_DOOR);\n              protocol_execute_realtime(); // Enter safety door mode.\n            }\n            \n            \n            mc_homing_cycle(); \n            if (!sys.abort) {  // Execute startup scripts after successful homing.\n              sys.state = STATE_IDLE; // Set to IDLE when complete.\n              st_go_idle(); // Set steppers to the settings idle state before returning.\n              system_execute_startup(line); \n            }\n          } else { return(STATUS_SETTING_DISABLED); }\n          break;\n        case 'I' : // Print or store build info. [IDLE/ALARM]\n          if ( line[++char_counter] == 0 ) { \n            settings_read_build_info(line);\n            report_build_info(line);\n          } else { // Store startup line [IDLE/ALARM]\n            if(line[char_counter++] != '=') { return(STATUS_INVALID_STATEMENT); }\n            helper_var = char_counter; // Set helper variable as counter to start of user info line.\n            do {\n              line[char_counter-helper_var] = line[char_counter];\n            } while (line[char_counter++] != 0);\n            settings_store_build_info(line);\n          }\n          break; \n        case 'R' : // Restore defaults [IDLE/ALARM]\n          if (line[++char_counter] != 'S') { return(STATUS_INVALID_STATEMENT); }\n          if (line[++char_counter] != 'T') { return(STATUS_INVALID_STATEMENT); }\n          if (line[++char_counter] != '=') { return(STATUS_INVALID_STATEMENT); }\n          if (line[char_counter+2] != 0) { return(STATUS_INVALID_STATEMENT); }                        \n          switch (line[++char_counter]) {\n            case '$': settings_restore(SETTINGS_RESTORE_DEFAULTS); break;\n            case '#': settings_restore(SETTINGS_RESTORE_PARAMETERS); break;\n            case '*': settings_restore(SETTINGS_RESTORE_ALL); break;\n            default: return(STATUS_INVALID_STATEMENT);\n          }\n          report_feedback_message(MESSAGE_RESTORE_DEFAULTS);\n          mc_reset(); // Force reset to ensure settings are initialized correctly.\n          break;\n        case 'N' : // Startup lines. [IDLE/ALARM]\n          if ( line[++char_counter] == 0 ) { // Print startup lines\n            for (helper_var=0; helper_var < N_STARTUP_LINE; helper_var++) {\n              if (!(settings_read_startup_line(helper_var, line))) {\n                report_status_message(STATUS_SETTING_READ_FAIL);\n              } else {\n                report_startup_line(helper_var,line);\n              }\n            }\n            break;\n          } else { // Store startup line [IDLE Only] Prevents motion during ALARM.\n            if (sys.state != STATE_IDLE) { return(STATUS_IDLE_ERROR); } // Store only when idle.\n            helper_var = true;  // Set helper_var to flag storing method. \n            // No break. Continues into default: to read remaining command characters.\n          }\n        default :  // Storing setting methods [IDLE/ALARM]\n          if(!read_float(line, &char_counter, &parameter)) { return(STATUS_BAD_NUMBER_FORMAT); }\n          if(line[char_counter++] != '=') { return(STATUS_INVALID_STATEMENT); }\n          if (helper_var) { // Store startup line\n            // Prepare sending gcode block to gcode parser by shifting all characters\n            helper_var = char_counter; // Set helper variable as counter to start of gcode block\n            do {\n              line[char_counter-helper_var] = line[char_counter];\n            } while (line[char_counter++] != 0);\n            // Execute gcode block to ensure block is valid.\n            helper_var = gc_execute_line(line); // Set helper_var to returned status code.\n            if (helper_var) { return(helper_var); }\n            else { \n              helper_var = trunc(parameter); // Set helper_var to int value of parameter\n              settings_store_startup_line(helper_var,line);\n            }\n          } else { // Store global setting.\n            if(!read_float(line, &char_counter, &value)) { return(STATUS_BAD_NUMBER_FORMAT); }\n            if((line[char_counter] != 0) || (parameter > 255)) { return(STATUS_INVALID_STATEMENT); }\n            return(settings_store_global_setting((uint8_t)parameter, value));\n          }\n      }    \n  }\n  return(STATUS_OK); // If '$' command makes it to here, then everything's ok.\n}\n\n\n// Returns machine position of axis 'idx'. Must be sent a 'step' array.\n// NOTE: If motor steps and machine position are not in the same coordinate frame, this function\n//   serves as a central place to compute the transformation.\nfloat system_convert_axis_steps_to_mpos(int32_t *steps, uint8_t idx)\n{\n  float pos;\n  #ifdef COREXY\n    if (idx==A_MOTOR) { \n      pos = 0.5*((steps[A_MOTOR] + steps[B_MOTOR])/settings.steps_per_mm[idx]);\n    } else if (idx==B_MOTOR) {\n      pos = 0.5*((steps[A_MOTOR] - steps[B_MOTOR])/settings.steps_per_mm[idx]);\n    } else {\n      pos = steps[idx]/settings.steps_per_mm[idx];\n    }\n  #else\n    pos = steps[idx]/settings.steps_per_mm[idx];\n  #endif\n  return(pos);\n}\n  \n\nvoid system_convert_array_steps_to_mpos(float *position, int32_t *steps)\n{\n  uint8_t idx;\n  for (idx=0; idx<N_AXIS; idx++) {\n    position[idx] = system_convert_axis_steps_to_mpos(steps, idx);\n  }\n  return;\n}\n"
  },
  {
    "path": "system.h",
    "content": "/*\n  system.h - Header for system level commands and real-time processes\n  Part of Grbl\n\n  Copyright (c) 2014-2015 Sungeun K. Jeon  \n\n  Grbl is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  Grbl is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#ifndef system_h\n#define system_h\n\n#include \"grbl.h\"\n\n// Define system executor bit map. Used internally by realtime protocol as realtime command flags, \n// which notifies the main program to execute the specified realtime command asynchronously.\n// NOTE: The system executor uses an unsigned 8-bit volatile variable (8 flag limit.) The default\n// flags are always false, so the realtime protocol only needs to check for a non-zero value to \n// know when there is a realtime command to execute.\n#define EXEC_STATUS_REPORT  bit(0) // bitmask 00000001\n#define EXEC_CYCLE_START    bit(1) // bitmask 00000010\n#define EXEC_CYCLE_STOP     bit(2) // bitmask 00000100\n#define EXEC_FEED_HOLD      bit(3) // bitmask 00001000\n#define EXEC_RESET          bit(4) // bitmask 00010000\n#define EXEC_SAFETY_DOOR    bit(5) // bitmask 00100000\n#define EXEC_MOTION_CANCEL  bit(6) // bitmask 01000000\n\n// Alarm executor bit map.\n// NOTE: EXEC_CRITICAL_EVENT is an optional flag that must be set with an alarm flag. When enabled,\n// this halts Grbl into an infinite loop until the user aknowledges the problem and issues a soft-\n// reset command. For example, a hard limit event needs this type of halt and aknowledgement.\n#define EXEC_CRITICAL_EVENT     bit(0) // bitmask 00000001 (SPECIAL FLAG. See NOTE:)\n#define EXEC_ALARM_HARD_LIMIT   bit(1) // bitmask 00000010\n#define EXEC_ALARM_SOFT_LIMIT   bit(2) // bitmask 00000100\n#define EXEC_ALARM_ABORT_CYCLE  bit(3) // bitmask 00001000\n#define EXEC_ALARM_PROBE_FAIL   bit(4) // bitmask 00010000\n#define EXEC_ALARM_HOMING_FAIL  bit(5) // bitmask 00100000\n\n// Define system state bit map. The state variable primarily tracks the individual functions\n// of Grbl to manage each without overlapping. It is also used as a messaging flag for\n// critical events.\n#define STATE_IDLE          0      // Must be zero. No flags.\n#define STATE_ALARM         bit(0) // In alarm state. Locks out all g-code processes. Allows settings access.\n#define STATE_CHECK_MODE    bit(1) // G-code check mode. Locks out planner and motion only.\n#define STATE_HOMING        bit(2) // Performing homing cycle\n#define STATE_CYCLE         bit(3) // Cycle is running or motions are being executed.\n#define STATE_HOLD          bit(4) // Active feed hold\n#define STATE_SAFETY_DOOR   bit(5) // Safety door is ajar. Feed holds and de-energizes system.\n#define STATE_MOTION_CANCEL bit(6) // Motion cancel by feed hold and return to idle. \n\n// Define system suspend states.\n#define SUSPEND_DISABLE       0      // Must be zero.\n#define SUSPEND_ENABLE_HOLD   bit(0) // Enabled. Indicates the cycle is active and currently undergoing a hold.\n#define SUSPEND_ENABLE_READY  bit(1) // Ready to resume with a cycle start command.\n#define SUSPEND_ENERGIZE      bit(2) // Re-energizes output before resume.\n#define SUSPEND_MOTION_CANCEL bit(3) // Cancels resume motion. Used by probing routine.\n\n\n// Define global system variables\ntypedef struct {\n  uint8_t abort;                 // System abort flag. Forces exit back to main loop for reset.\n  uint8_t state;                 // Tracks the current state of Grbl.\n  uint8_t suspend;               // System suspend bitflag variable that manages holds, cancels, and safety door.\n\n  volatile uint8_t rt_exec_state;  // Global realtime executor bitflag variable for state management. See EXEC bitmasks.\n  volatile uint8_t rt_exec_alarm;  // Global realtime executor bitflag variable for setting various alarms.\n\n  int32_t position[N_AXIS];      // Real-time machine (aka home) position vector in steps. \n                                 // NOTE: This may need to be a volatile variable, if problems arise.                             \n\n  uint8_t homing_axis_lock;       // Locks axes when limits engage. Used as an axis motion mask in the stepper ISR.\n  volatile uint8_t probe_state;   // Probing state value.  Used to coordinate the probing cycle with stepper ISR.\n  int32_t probe_position[N_AXIS]; // Last probe position in machine coordinates and steps.\n  uint8_t probe_succeeded;        // Tracks if last probing cycle was successful.\n} system_t;\nextern system_t sys;\n\n\n// Initialize the serial protocol\nvoid system_init();\n\n// Returns if safety door is open or closed, based on pin state.\nuint8_t system_check_safety_door_ajar();\n\n// Executes an internal system command, defined as a string starting with a '$'\nuint8_t system_execute_line(char *line);\n\n// Execute the startup script lines stored in EEPROM upon initialization\nvoid system_execute_startup(char *line);\n\n// Returns machine position of axis 'idx'. Must be sent a 'step' array.\nfloat system_convert_axis_steps_to_mpos(int32_t *steps, uint8_t idx);\n\n// Updates a machine 'position' array based on the 'step' array sent.\nvoid system_convert_array_steps_to_mpos(float *position, int32_t *steps);\n\n#endif\n"
  }
]