diff --git a/DOCKER_LICENSE b/DOCKER_LICENSE new file mode 100644 index 0000000..8ca52e7 --- /dev/null +++ b/DOCKER_LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Ryan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/DOCKER_README.md b/DOCKER_README.md new file mode 100644 index 0000000..d560165 --- /dev/null +++ b/DOCKER_README.md @@ -0,0 +1,32 @@ +# Arm Embedded Docker Environment +Minimal docker environment for building arm-embedded projects + +## Usage +Run interactively with ```docker run -it --rm -v `pwd`:/root ryankurte/docker-arm-embedded /bin/bash```. +This will create a temporal instance (changes will be dropped on exit) with a binding from the current directory to the root user home directory. + +If you are using selinux you may need to add a ```:z``` to the end of the -v parameter to indicate the mount is shared. + +```docker run -it --rm -v `pwd`:/root:z ryankurte/docker-arm-embedded /bin/bash``` + +https://docs.docker.com/storage/bind-mounts/ + +### Building grbl-LPC +Update the grbl/config.h and uncomment the CPU_MAP define statement for the board you are compiling for + +``` +git submodule init +git submodule update +make +``` + +The resulting firmware file is build/firmware.bin + +## Includes: + - build-essential (native) + - make, cmake + - gawk, genromfs, ccache + - arm-none-eabi from [launchpad.net](https://launchpad.net/~terry.guo/+archive/ubuntu/gcc-arm-embedded) + - [Yotta](http://yotta.mbed.com/) + + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..717312d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,62 @@ +FROM ubuntu:latest +MAINTAINER Ryan Kurte +LABEL Description="Docker image for building arm-embedded projects" + +# General dependencies +RUN apt-get update && apt-get install -y \ + git \ + subversion \ + curl \ + cmake \ + make \ + automake \ + autoconf \ + python-setuptools \ + ninja-build \ + python-dev \ + libtool \ + unzip \ + libffi-dev \ + libssl-dev \ + libusb-1.0.0 \ + libusb-1.0.0-dev \ + software-properties-common \ + python-software-properties \ + gawk \ + genromfs \ + ccache \ + clang \ + build-essential \ + python3 \ + python3-dev \ + python3-pip \ + libprotobuf-dev \ + protobuf-compiler \ + libprotobuf-c-dev \ + protobuf-c-compiler \ + python-protobuf + +# arm-none-eabi custom ppa +RUN add-apt-repository ppa:team-gcc-arm-embedded/ppa && \ + apt-get update && \ + apt-get install -y gcc-arm-embedded + +# Yotta +RUN easy_install pip && \ + pip install yotta && \ + mkdir -p /usr/local/lib/yotta_modules \ + chown $USER /usr/local/lib/yotta_modules \ + chmod 755 /usr/local/lib/yotta_modules + +# Pyserial for serial programming +RUN pip install pyserial + +# STLink util +RUN git clone https://github.com/texane/stlink.git && \ + cd stlink && mkdir build && cd build && \ + cmake .. && make && make install + +# Cleanup +RUN apt-get clean && \ + rm -rf /var/lib/apt + diff --git a/README.md b/README.md index 24a28c7..b325bdc 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,18 @@ ![GitHub Logo](https://github.com/gnea/gnea-Media/blob/master/Grbl%20Logo/Grbl%20Logo%20250px.png?raw=true) *** -Old releases are in the `Release` tab. See [cprezzi's branch](https://github.com/cprezzi/grbl-LPC) for more recent releases. -Note: cprezzi's branch disables current control and has defaults more suitable for other boards. +Note: this branch defaults stepper current to zero and has defaults for more boards and machines. *** -This is GRBL 1.1 ported to the LPC1769. It can run on Smoothieboard. +This is GRBL 1.1 ported to the LPC1769. +It can run on the following boards: +- Smoothieboard +- Cohesion3D Remix and Mini +- MKS SBase +- Azteeg X5 -Usage notes: +SKR boards don't work, because pin mapping is messed! + +**Usage notes:** * This uses a different usb-serial driver than Smoothieware. Windows 10 should recognize it automatically. If it doesn't, try installing VCOM_lib/usbser.inf. * This doesn't pass the sdcard to the host. Once installed you need to use a micro sdcard adaptor to replace or change it. @@ -24,14 +30,17 @@ New configuration settings * $34 is PWM off value in % * $35 is PWM min value in % * $36 is PWM max value in % -* $140, $141, $142 are X, Y, Z current (amps) +* $140, $141, $142, $143 are X, Y, Z, E0 current (amps) * Default to 0.0 A to avoid burning out your motors * Your motors will likely stall if you don't set these! -Build notes: +**Build notes:** +* You should use virtual machines, if you use multiple toolchains on the same PC. +* Install make if not already there (for Windows see http://gnuwin32.sourceforge.net/packages/make.htm) +* Install the ARM embeded toolchain (see https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) * Include ```make``` and the ```arm-none-eabi-*``` tools in your path. * Run ```git submodule init``` and ```git submodule update``` before building. -* Make produces 2 files: +* Run ```make```, which produces 2 files: * ```build/firmware.bin```: this is compatible with the sdcard bootloader. * ```build/grbl.hex```: this is not compatible with the sdcard bootloader. It loads using Flash Magic and is primarilly for developers who don't want to keep swapping sdcards. If you flash this, diff --git a/doc/markdown/settings.md b/doc/markdown/settings.md index 4b54746..f653c8c 100644 --- a/doc/markdown/settings.md +++ b/doc/markdown/settings.md @@ -51,6 +51,7 @@ $27=1.000 $30=1000. $31=0. $32=0 +$33=5000 $100=250.000 $101=250.000 $102=250.000 @@ -63,6 +64,9 @@ $122=10.000 $130=200.000 $131=200.000 $132=200.000 +$140=0.000 +$141=0.000 +$142=0.000 ``` #### $x=val - Save Grbl setting @@ -227,6 +231,10 @@ When enabled, Grbl will move continuously through consecutive `G1`, `G2`, or `G3 When disabled, Grbl will operate as it always has, stopping motion with every `S` spindle speed command. This is the default operation of a milling machine to allow a pause to let the spindle change speeds. +#### $33 - Spindle/Laser PWM frequency + +This sets the PWM frequency. + #### $100, $101 and $102 – [X,Y,Z] steps/mm Grbl needs to know how far each step will take the tool in reality. To calculate steps/mm for an axis of your machine you need to know: diff --git a/doc/media/Thumbs.db b/doc/media/Thumbs.db new file mode 100644 index 0000000..4715c4b Binary files /dev/null and b/doc/media/Thumbs.db differ diff --git a/grbl-lpc/current_control.cpp b/grbl-lpc/current_control.cpp index ab8f0de..02fc675 100644 --- a/grbl-lpc/current_control.cpp +++ b/grbl-lpc/current_control.cpp @@ -55,7 +55,7 @@ void current_init() set_current(0, settings.current[0]); set_current(1, settings.current[1]); set_current(2, settings.current[2]); - set_current(3, DEFAULT_A_CURRENT); + set_current(3, settings.current[3]); #endif } diff --git a/grbl-lpc/delay.cpp b/grbl-lpc/delay.cpp index 653c261..2754a27 100644 --- a/grbl-lpc/delay.cpp +++ b/grbl-lpc/delay.cpp @@ -22,11 +22,11 @@ void delay_init() { - LPC_TIM3->CTCR = 0; // timer mode - LPC_TIM3->PR = 0; // no prescale - LPC_TIM3->MCR = 0; // no MR actions - LPC_TIM3->CCR = 0; // no capture - LPC_TIM3->EMR = 0; // no external match - LPC_TIM3->TCR = 0b10; // reset - LPC_TIM3->TCR = 0b01; // enable + LPC_TIM3->CTCR = 0; // Count Control (0=TimerMode, 1-3=EdgeCounterMode) + LPC_TIM3->PR = 0; // no Prescale (TC increments ever PR+1 clocks) + LPC_TIM3->MCR = 0; // no Match Control actions + LPC_TIM3->CCR = 0; // no Capture Control actions + LPC_TIM3->EMR = 0; // no External Match (controls external match pins) + LPC_TIM3->TCR = 0b10; // reset Timer Control (0b10=Reset, 0b01=Enable) + LPC_TIM3->TCR = 0b01; // enable Timer Control (0b10=Reset, 0b01=Enable) } diff --git a/grbl-lpc/flash.cpp b/grbl-lpc/flash.cpp index a42b843..7cf1034 100644 --- a/grbl-lpc/flash.cpp +++ b/grbl-lpc/flash.cpp @@ -25,37 +25,38 @@ static constexpr unsigned flash_addr = 0xF000; // Last 4k sec static constexpr unsigned flash_size = 1024; // Only using 1k of a 4k sector static char *flash_memory = (char *)flash_addr; // Flash memory static char flash_buffer[flash_size] __attribute__((aligned(4))); // Copy of flash memory -using Iap = void(unsigned[], unsigned[]); // IAP entry point -static const Iap *iap = (Iap *)0x1FFF1FF1; // IAP entry point +using Iap = void(unsigned[], unsigned[]); // IAP entry point function +static const Iap *iap = (Iap *)0x1FFF1FF1; // IAP entry point address void eeprom_init() { - memcpy(flash_buffer, flash_memory, flash_size); + memcpy(flash_buffer, flash_memory, flash_size); // Copy flash memory into local flash buffer } void eeprom_commit() { if (!memcmp(flash_buffer, flash_memory, flash_size)) - return; + return; // No changes to commit unsigned prepCommand[5] = { - 50, - flash_sector, - flash_sector, + 50, // Prepare sector(s) for write operation + flash_sector, // Start sector + flash_sector, // End sector }; unsigned eraseCommand[5] = { - 52, - flash_sector, - flash_sector, - SystemCoreClock / 1000, + 52, // Erase sector(s) + flash_sector, // Start sector + flash_sector, // End sector + SystemCoreClock / 1000, // CPU clock frequency in kHz }; unsigned writeCommand[5] = { - 51, - flash_addr, - (unsigned)flash_buffer, - flash_size, - SystemCoreClock / 1000, + 51, // Copy RAM to Flash + flash_addr, // Destination flash address (256-byte boundary) + (unsigned)flash_buffer, // Source RAM address (word boundary) + flash_size, // Number of bytes to write (must be: 256, 512, 1024, 4096) + SystemCoreClock / 1000, // CPU clock frequency in kHz }; unsigned output[5]; + // Run In-Application Programming (IAP) routines iap(prepCommand, output); iap(eraseCommand, output); iap(prepCommand, output); diff --git a/grbl/config.h b/grbl/config.h index 238cbdc..8598743 100644 --- a/grbl/config.h +++ b/grbl/config.h @@ -31,12 +31,22 @@ #include "LPC17xx.h" -// Define CPU pin map and default settings. -// NOTE: OEMs can avoid the need to maintain/update the defaults.h and cpu_map.h files and use only -// one configuration file by placing their specific defaults and pin map at the bottom of this file. -// If doing so, simply comment out these two defines and see instructions below. -// #define DEFAULTS_GENERIC -// #define CPU_MAP_ATMEGA328P // Arduino Uno CPU +// Define board type for pin map and default settings. +#define CPU_MAP_SMOOTHIEBOARD // Smoothieboard (NXP LPC1769 MCU) +//#define CPU_MAP_C3D_REMIX // Cohesion3D Remix (NXP LPC1769 MCU) +//#define CPU_MAP_C3D_MINI // Cohesion3D Mini (NXP LPC1769 MCU) +//#define CPU_MAP_MKS_SBASE // MKS SBASE Board (NXP LPC1768 MCU) +//#define CPU_MAP_AZTEEG_X5 // Azteeg X5 Board (NXP LPC1769 MCU) + +// Force other Spindle PWM Pin (default is P2.5) +//#define SPINDLE_PWM_PIN_1_23 +//#define SPINDLE_PWM_PIN_2_4 + +// Define machine type for machine specific defaults +//#define DEFAULTS_GENERIC +#define DEFAULTS_K40 +//#define DEFAULTS_FABKIT +//#define DEFAULTS_JONAS // Serial baud rate // #define BAUD_RATE 230400 @@ -103,8 +113,9 @@ // on separate pin, but homed in one cycle. Also, it should be noted that the function of hard limits // will not be affected by pin sharing. // NOTE: Defaults are set for a traditional 3-axis CNC machine. Z-axis first to clear, followed by X & Y. -#define HOMING_CYCLE_0 (1<FIODIR -#define STEP_PORT LPC_GPIO2->FIOPIN -#define X_STEP_BIT 0 -#define Y_STEP_BIT 1 -#define Z_STEP_BIT 2 -#define STEP_MASK ((1<FIODIR -#define DIRECTION_PORT LPC_GPIO0->FIOPIN -#define X_DIRECTION_BIT 5 -#define Y_DIRECTION_BIT 11 -#define Z_DIRECTION_BIT 20 -#define DIRECTION_MASK ((1<FIODIR -#define STEPPERS_DISABLE_PORT LPC_GPIO0->FIOPIN -#define X_DISABLE_BIT 4 -#define Y_DISABLE_BIT 10 -#define Z_DISABLE_BIT 19 -#define STEPPERS_DISABLE_MASK ((1<FIODIR -#define LIMIT_PIN LPC_GPIO1->FIOPIN -#define LIMIT_PORT LPC_GPIO1->FIOPIN -#define X_LIMIT_BIT 25 // X-MIN=24, X-MAX=25 -#define Y_LIMIT_BIT 27 // Y-MIN=26, Y-MAX=27 -#define Z_LIMIT_BIT 29 // Z-MIN=28, Z-MAX=29 -#define LIMIT_MASK ((1< 0.98kHz (J-tech laser) // NOTE: On the 328p, these must be the same as the SPINDLE_ENABLE settings. - #define SPINDLE_PWM_DDR DDRB - #define SPINDLE_PWM_PORT PORTB - #define SPINDLE_PWM_BIT 3 // Uno Digital Pin 11 + #define SPINDLE_PWM_DDR DDRB + #define SPINDLE_PWM_PORT PORTB + #define SPINDLE_PWM_BIT 3 // Uno Digital Pin 11 + +#endif // end of CPU_MAP_ATMEGA328P + + +#ifdef CPU_MAP_SMOOTHIEBOARD // (Smoothieboards) + + // Define serial port pins and interrupt vectors. + #define SERIAL_RX USART_RX_vect + #define SERIAL_UDRE USART_UDRE_vect + + // Define step pulse output pins. NOTE: All step bit pins must be on the same port. + #define STEP_DDR LPC_GPIO2->FIODIR + #define STEP_PORT LPC_GPIO2->FIOPIN + #define X_STEP_BIT 0 + #define Y_STEP_BIT 1 + #define Z_STEP_BIT 2 + #define A_STEP_BIT 3 + #define STEP_MASK ((1<FIODIR + #define DIRECTION_PORT LPC_GPIO0->FIOPIN + #define X_DIRECTION_BIT 5 + #define Y_DIRECTION_BIT 11 + #define Z_DIRECTION_BIT 20 + #define A_DIRECTION_BIT 22 + #define DIRECTION_MASK ((1<FIODIR + #define STEPPERS_DISABLE_PORT LPC_GPIO0->FIOPIN + #define X_DISABLE_BIT 4 + #define Y_DISABLE_BIT 10 + #define Z_DISABLE_BIT 19 + #define A_DISABLE_BIT 21 + #define STEPPERS_DISABLE_MASK ((1<FIODIR + #define LIMIT_PIN LPC_GPIO1->FIOPIN + #define LIMIT_PORT LPC_GPIO1->FIOPIN + #define X_LIMIT_BIT 24 // X-MIN=24, X-MAX=25 + #define Y_LIMIT_BIT 26 // Y-MIN=26, Y-MAX=27 + #define Z_LIMIT_BIT 28 // Z-MIN=28, Z-MAX=29 + #define A_LIMIT_BIT 29 // reuse Z-MAX (P1.29) + #define LIMIT_MASK ((1<FIODIR + #define SPINDLE_ENABLE_PORT LPC_GPIO1->FIOPIN + #define SPINDLE_ENABLE_BIT 30 // P1.30 + #define SPINDLE_DIRECTION_DDR LPC_GPIO1->FIODIR + #define SPINDLE_DIRECTION_PORT LPC_GPIO1->FIOPIN + #define SPINDLE_DIRECTION_BIT 31 // P1.31 + + // Define flood and mist coolant enable output pins. + #define COOLANT_FLOOD_DDR LPC_GPIO2->FIODIR + #define COOLANT_FLOOD_PORT LPC_GPIO2->FIOPIN + #ifndef SPINDLE_PWM_PIN_2_4 + #define COOLANT_FLOOD_BIT 4 // SMALL MOSFET Q8 (P2.4) + #else + #define COOLANT_FLOOD_BIT 5 // SMALL MOSFET Q8 (P2.5) + #endif + #define COOLANT_MIST_DDR LPC_GPIO2->FIODIR + #define COOLANT_MIST_PORT LPC_GPIO2->FIOPIN + #define COOLANT_MIST_BIT 6 // SMALL MOSFET Q9 (P2.6) + #define ENABLE_M7 // enables COOLANT MIST + + // Define user-control controls (cycle start, reset, feed hold) input pins. + // NOTE: All CONTROLs pins must be on the same port and not on a port with other input pins (limits). + #define CONTROL_DDR LPC_GPIO1->FIODIR + #define CONTROL_PIN LPC_GPIO1->FIOPIN + #define CONTROL_PORT LPC_GPIO1->FIOPIN + #define CONTROL_RESET_BIT NotUsed // Not needed as there is a special RESET pin on the Smoothiebaord + #define CONTROL_FEED_HOLD_BIT 22 // P1.22 + #define CONTROL_CYCLE_START_BIT 23 // P1.23 + #define CONTROL_SAFETY_DOOR_BIT 22 // P1.22 NOTE: Safety door is shared with feed hold. Enabled by config define. + #define CONTROL_INT PCIE1 // Pin change interrupt enable pin + #define CONTROL_INT_vect PCINT1_vect + #define CONTROL_PCMSK NotUsed // Pin change interrupt register + #define CONTROL_MASK ((1<FIODIR + #define PROBE_PIN LPC_GPIO2->FIOPIN + #define PROBE_PORT LPC_GPIO2->FIOPIN + #define PROBE_BIT 11 // P2.11 + #define PROBE_MASK (1<FIODIR + #define STEP_PORT LPC_GPIO2->FIOPIN + #define X_STEP_BIT 0 + #define Y_STEP_BIT 1 + #define Z_STEP_BIT 2 + #define A_STEP_BIT 3 + #define STEP_MASK ((1<FIODIR + #define DIRECTION_PORT LPC_GPIO0->FIOPIN + #define X_DIRECTION_BIT 5 + #define Y_DIRECTION_BIT 11 + #define Z_DIRECTION_BIT 20 + #define A_DIRECTION_BIT 22 + #define DIRECTION_MASK ((1<FIODIR + #define STEPPERS_DISABLE_PORT LPC_GPIO0->FIOPIN + #define X_DISABLE_BIT 4 + #define Y_DISABLE_BIT 10 + #define Z_DISABLE_BIT 19 + #define A_DISABLE_BIT 21 + #define STEPPERS_DISABLE_MASK ((1<FIODIR + #define LIMIT_PIN LPC_GPIO1->FIOPIN + #define LIMIT_PORT LPC_GPIO1->FIOPIN + #define X_LIMIT_BIT 24 // X-MIN=24, X-MAX=25 + #define Y_LIMIT_BIT 26 // Y-MIN=26, Y-MAX=27 + #define Z_LIMIT_BIT 28 // Z-MIN=28, Z-MAX=29 + #define A_LIMIT_BIT 29 // reuse p1.29 from Z-MAX + #define LIMIT_MASK ((1<FIODIR + #define SPINDLE_ENABLE_PORT LPC_GPIO1->FIOPIN + #define SPINDLE_ENABLE_BIT 30 // P1.30 + #define SPINDLE_DIRECTION_DDR LPC_GPIO1->FIODIR + #define SPINDLE_DIRECTION_PORT LPC_GPIO1->FIOPIN + #define SPINDLE_DIRECTION_BIT 31 // P1.31 + + // Define flood and mist coolant enable output pins. + #define COOLANT_FLOOD_DDR LPC_GPIO2->FIODIR + #define COOLANT_FLOOD_PORT LPC_GPIO2->FIOPIN + #define COOLANT_FLOOD_BIT 6 // MOSFET 2.6 + #define COOLANT_MIST_DDR LPC_GPIO2->FIODIR + #define COOLANT_MIST_PORT LPC_GPIO2->FIOPIN + #define COOLANT_MIST_BIT 7 // MOSFET 2.7 + #define ENABLE_M7 // enables COOLANT MIST + + // Define user-control controls (cycle start, reset, feed hold) input pins. + // NOTE: All CONTROLs pins must be on the same port and not on a port with other input pins (limits). + #define CONTROL_DDR NotUsed + #define CONTROL_PIN NotUsed + #define CONTROL_PORT NotUsed + #define CONTROL_RESET_BIT 0 // Uno Analog Pin 0 + #define CONTROL_FEED_HOLD_BIT 1 // Uno Analog Pin 1 + #define CONTROL_CYCLE_START_BIT 2 // Uno Analog Pin 2 + #define CONTROL_SAFETY_DOOR_BIT 1 // Uno Analog Pin 1 NOTE: Safety door is shared with feed hold. Enabled by config define. + #define CONTROL_INT PCIE1 // Pin change interrupt enable pin + #define CONTROL_INT_vect PCINT1_vect + #define CONTROL_PCMSK NotUsed // Pin change interrupt register + #define CONTROL_MASK ((1<FIODIR + #define PROBE_PIN LPC_GPIO1->FIOPIN + #define PROBE_PORT LPC_GPIO1->FIOPIN + #define PROBE_BIT 27 // reuse P1.27 from Y-MAX + #define PROBE_MASK (1<FIODIR + #define STEP_PORT LPC_GPIO2->FIOPIN + #define X_STEP_BIT 0 + #define Y_STEP_BIT 1 + #define Z_STEP_BIT 2 + #define A_STEP_BIT 3 + #define STEP_MASK ((1<FIODIR + #define DIRECTION_PORT LPC_GPIO0->FIOPIN + #define X_DIRECTION_BIT 5 + #define Y_DIRECTION_BIT 11 + #define Z_DIRECTION_BIT 20 + #define A_DIRECTION_BIT 22 + #define DIRECTION_MASK ((1<FIODIR + #define STEPPERS_DISABLE_PORT LPC_GPIO0->FIOPIN + #define X_DISABLE_BIT 4 + #define Y_DISABLE_BIT 10 + #define Z_DISABLE_BIT 19 + #define A_DISABLE_BIT 21 + #define STEPPERS_DISABLE_MASK ((1<FIODIR + #define LIMIT_PIN LPC_GPIO1->FIOPIN + #define LIMIT_PORT LPC_GPIO1->FIOPIN + #define X_LIMIT_BIT 24 // X-MIN=24, X-MAX=25 + #define Y_LIMIT_BIT 26 // Y-MIN=26, Y-MAX=27 + #define Z_LIMIT_BIT 28 // Z-MIN=28, Z-MAX=29 + #define A_LIMIT_BIT 29 // reuse p1.29 from Z-MAX + #define LIMIT_MASK ((1<FIODIR + #define SPINDLE_DIRECTION_PORT LPC_GPIO1->FIOPIN + #define SPINDLE_DIRECTION_BIT 31 // P1.31 + + // Define flood and mist coolant enable output pins. + #define COOLANT_FLOOD_DDR NotUsed + #define COOLANT_FLOOD_PORT NotUsed + #define COOLANT_FLOOD_BIT 6 // MOSFET 3 (P2.6) + #define COOLANT_MIST_DDR LPC_GPIO2->FIODIR + #define COOLANT_MIST_PORT LPC_GPIO2->FIOPIN + #define COOLANT_MIST_BIT 7 // MOSFET 2 (P2.7) + #define ENABLE_M7 // enables COOLANT MIST + + // Define user-control controls (cycle start, reset, feed hold) input pins. + // NOTE: All CONTROLs pins must be on the same port and not on a port with other input pins (limits). + #define CONTROL_DDR NotUsed + #define CONTROL_PIN NotUsed + #define CONTROL_PORT NotUsed + #define CONTROL_RESET_BIT 0 // Uno Analog Pin 0 + #define CONTROL_FEED_HOLD_BIT 1 // Uno Analog Pin 1 + #define CONTROL_CYCLE_START_BIT 2 // Uno Analog Pin 2 + #define CONTROL_SAFETY_DOOR_BIT 1 // Uno Analog Pin 1 NOTE: Safety door is shared with feed hold. Enabled by config define. + #define CONTROL_INT PCIE1 // Pin change interrupt enable pin + #define CONTROL_INT_vect PCINT1_vect + #define CONTROL_PCMSK NotUsed // Pin change interrupt register + #define CONTROL_MASK ((1<FIODIR + #define PROBE_PIN LPC_GPIO1->FIOPIN + #define PROBE_PORT LPC_GPIO1->FIOPIN + #define PROBE_BIT 27 // reuse P1.27 from Y-MAX + #define PROBE_MASK (1<FIODIR + #define STEP_PORT LPC_GPIO2->FIOPIN + #define X_STEP_BIT 0 + #define Y_STEP_BIT 1 + #define Z_STEP_BIT 2 + #define A_STEP_BIT 3 + #define STEP_MASK ((1<FIODIR + #define DIRECTION_PORT LPC_GPIO0->FIOPIN + #define X_DIRECTION_BIT 5 + #define Y_DIRECTION_BIT 11 + #define Z_DIRECTION_BIT 20 + #define A_DIRECTION_BIT 22 + #define DIRECTION_MASK ((1<FIODIR + #define STEPPERS_DISABLE_PORT LPC_GPIO0->FIOPIN + #define X_DISABLE_BIT 4 + #define Y_DISABLE_BIT 10 + #define Z_DISABLE_BIT 19 + #define A_DISABLE_BIT 21 + #define STEPPERS_DISABLE_MASK ((1<FIODIR + #define LIMIT_PIN LPC_GPIO1->FIOPIN + #define LIMIT_PORT LPC_GPIO1->FIOPIN + #define X_LIMIT_BIT 24 // X-MIN=24, X-MAX=25 + #define Y_LIMIT_BIT 26 // Y-MIN=26, Y-MAX=27 + #define Z_LIMIT_BIT 28 // Z-MIN=28, Z-MAX=29 + #define A_LIMIT_BIT 29 // reuse p1.29 + #define LIMIT_MASK ((1<FIODIR + #define SPINDLE_ENABLE_PORT LPC_GPIO1->FIOPIN + #define SPINDLE_ENABLE_BIT 30 // P1.30 + #define SPINDLE_DIRECTION_DDR LPC_GPIO1->FIODIR + #define SPINDLE_DIRECTION_PORT LPC_GPIO1->FIOPIN + #define SPINDLE_DIRECTION_BIT 31 // P1.31 + + // Define flood and mist coolant enable output pins. + #define COOLANT_FLOOD_DDR LPC_GPIO2->FIODIR + #define COOLANT_FLOOD_PORT LPC_GPIO2->FIOPIN + #define COOLANT_FLOOD_BIT 6 // MOSFET 2.6 + #define COOLANT_MIST_DDR LPC_GPIO2->FIODIR + #define COOLANT_MIST_PORT LPC_GPIO2->FIOPIN + #define COOLANT_MIST_BIT 7 // MOSFET 2.7 + #define ENABLE_M7 // enables COOLANT MIST + + // Define user-control controls (cycle start, reset, feed hold) input pins. + // NOTE: All CONTROLs pins must be on the same port and not on a port with other input pins (limits). + #define CONTROL_DDR LPC_GPIO1->FIODIR + #define CONTROL_PIN LPC_GPIO1->FIOPIN + #define CONTROL_PORT LPC_GPIO1->FIOPIN + #define CONTROL_RESET_BIT NotUsed // Not needed as there is a special RESET pin on the Smoothiebaord + #define CONTROL_FEED_HOLD_BIT 22 // P1.22 + #define CONTROL_CYCLE_START_BIT 23 // P1.23 + #define CONTROL_SAFETY_DOOR_BIT 22 // P1.22 NOTE: Safety door is shared with feed hold. Enabled by config define. + #define CONTROL_INT PCIE1 // Pin change interrupt enable pin + #define CONTROL_INT_vect PCINT1_vect + #define CONTROL_PCMSK NotUsed // Pin change interrupt register + #define CONTROL_MASK ((1<FIODIR + #define PROBE_PIN LPC_GPIO1->FIOPIN + #define PROBE_PORT LPC_GPIO1->FIOPIN + #define PROBE_BIT 27 // reuse P1.27 from Y-MAX + #define PROBE_MASK (1<FIODIR + #define STEP_PORT LPC_GPIO2->FIOPIN + #define X_STEP_BIT 1 + #define Y_STEP_BIT 2 + #define Z_STEP_BIT 3 + #define A_STEP_BIT 0 + #define STEP_MASK ((1<FIODIR + #define DIRECTION_PORT LPC_GPIO0->FIOPIN + #define X_DIRECTION_BIT 11 + #define Y_DIRECTION_BIT 20 + #define Z_DIRECTION_BIT 22 + #define A_DIRECTION_BIT 5 + #define DIRECTION_MASK ((1<FIODIR + #define STEPPERS_DISABLE_PORT LPC_GPIO0->FIOPIN + #define X_DISABLE_BIT 10 + #define Y_DISABLE_BIT 19 + #define Z_DISABLE_BIT 21 + #define A_DISABLE_BIT 4 + #define STEPPERS_DISABLE_MASK ((1<FIODIR + #define LIMIT_PIN LPC_GPIO1->FIOPIN + #define LIMIT_PORT LPC_GPIO1->FIOPIN + #define X_LIMIT_BIT 24 // X-MIN=24, X-MAX=27 + #define Y_LIMIT_BIT 25 // Y-MIN=25, Y-MAX=28 + #define Z_LIMIT_BIT 26 // Z-MIN=26, Z-MAX=29 + #define A_LIMIT_BIT 27 // reuse p1.27, as X-MAX is not used + #define LIMIT_MASK ((1<FIODIR + #define SPINDLE_ENABLE_PORT LPC_GPIO1->FIOPIN + #define SPINDLE_ENABLE_BIT 30 // P1.30 + #define SPINDLE_DIRECTION_DDR LPC_GPIO1->FIODIR + #define SPINDLE_DIRECTION_PORT LPC_GPIO1->FIOPIN + #define SPINDLE_DIRECTION_BIT 31 // P1.31 + + // Define flood and mist coolant enable output pins. + #define COOLANT_FLOOD_DDR LPC_GPIO2->FIODIR + #define COOLANT_FLOOD_PORT LPC_GPIO2->FIOPIN + #define COOLANT_FLOOD_BIT 4 // FAN MOSFET (P2.4) + #define COOLANT_MIST_DDR LPC_GPIO2->FIODIR + #define COOLANT_MIST_PORT LPC_GPIO2->FIOPIN + #define COOLANT_MIST_BIT 7 // BED MOSFET (P2.7) + #define ENABLE_M7 // enables COOLANT MIST + + // Define user-control controls (cycle start, reset, feed hold) input pins. + // NOTE: All CONTROLs pins must be on the same port and not on a port with other input pins (limits). + #define CONTROL_DDR NotUsed + #define CONTROL_PIN NotUsed + #define CONTROL_PORT NotUsed + #define CONTROL_RESET_BIT 0 // Uno Analog Pin 0 + #define CONTROL_FEED_HOLD_BIT 1 // Uno Analog Pin 1 + #define CONTROL_CYCLE_START_BIT 2 // Uno Analog Pin 2 + #define CONTROL_SAFETY_DOOR_BIT 1 // Uno Analog Pin 1 NOTE: Safety door is shared with feed hold. Enabled by config define. + #define CONTROL_INT PCIE1 // Pin change interrupt enable pin + #define CONTROL_INT_vect PCINT1_vect + #define CONTROL_PCMSK NotUsed // Pin change interrupt register + #define CONTROL_MASK ((1< MAX_TOOL_NUMBER) { FAIL(STATUS_GCODE_MAX_VALUE_EXCEEDED); } + if (value > MAX_TOOL_NUMBER) { FAIL(STATUS_GCODE_MAX_VALUE_EXCEEDED); } gc_block.values.t = int_value; - break; - case 'X': word_bit = WORD_X; gc_block.values.xyz[X_AXIS] = value; axis_words |= (1< WCS = MPos - G92 - TLO - WPos - gc_block.values.ijk[idx] = gc_state.position[idx]-gc_state.coord_offset[idx]-gc_block.values.xyz[idx]; + gc_block.values.ijk[idx] = gc_state.position[idx]-gc_state.coord_offset[idx]-gc_block.values.xyza[idx]; if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.ijk[idx] -= gc_state.tool_length_offset; } } else { // L2: Update coordinate system axis to programmed value. - gc_block.values.ijk[idx] = gc_block.values.xyz[idx]; + gc_block.values.ijk[idx] = gc_block.values.xyza[idx]; } } // Else, keep current stored value. } @@ -567,10 +567,10 @@ uint8_t gc_execute_line(char *line) for (idx=0; idx G92 = MPos - WCS - TLO - WPos - gc_block.values.xyz[idx] = gc_state.position[idx]-block_coord_system[idx]-gc_block.values.xyz[idx]; - if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.xyz[idx] -= gc_state.tool_length_offset; } + gc_block.values.xyza[idx] = gc_state.position[idx]-block_coord_system[idx]-gc_block.values.xyza[idx]; + if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.xyza[idx] -= gc_state.tool_length_offset; } } else { - gc_block.values.xyz[idx] = gc_state.coord_offset[idx]; + gc_block.values.xyza[idx] = gc_state.coord_offset[idx]; } } break; @@ -585,17 +585,17 @@ uint8_t gc_execute_line(char *line) if (axis_words) { for (idx=0; idxcondition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. - if (axis_command) { mc_line(gc_block.values.xyz, pl_data); } + if (axis_command) { mc_line(gc_block.values.xyza, pl_data); } mc_line(gc_block.values.ijk, pl_data); memcpy(gc_state.position, gc_block.values.ijk, N_AXIS*sizeof(float)); break; @@ -1033,7 +1033,7 @@ uint8_t gc_execute_line(char *line) settings_write_coord_data(SETTING_INDEX_G30,gc_state.position,false,true); break; case NON_MODAL_SET_COORDINATE_OFFSET: - memcpy(gc_state.coord_offset,gc_block.values.xyz,sizeof(gc_block.values.xyz)); + memcpy(gc_state.coord_offset,gc_block.values.xyza,sizeof(gc_block.values.xyza)); system_flag_wco_change(); break; case NON_MODAL_RESET_COORDINATE_OFFSET: @@ -1051,27 +1051,27 @@ uint8_t gc_execute_line(char *line) if (axis_command == AXIS_COMMAND_MOTION_MODE) { uint8_t gc_update_pos = GC_UPDATE_POS_TARGET; if (gc_state.modal.motion == MOTION_MODE_LINEAR) { - mc_line(gc_block.values.xyz, pl_data); + mc_line(gc_block.values.xyza, pl_data); } else if (gc_state.modal.motion == MOTION_MODE_SEEK) { pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. - mc_line(gc_block.values.xyz, pl_data); + mc_line(gc_block.values.xyza, pl_data); } else if ((gc_state.modal.motion == MOTION_MODE_CW_ARC) || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) { - mc_arc(gc_block.values.xyz, pl_data, gc_state.position, gc_block.values.ijk, gc_block.values.r, + mc_arc(gc_block.values.xyza, pl_data, gc_state.position, gc_block.values.ijk, gc_block.values.r, axis_0, axis_1, axis_linear, bit_istrue(gc_parser_flags,GC_PARSER_ARC_IS_CLOCKWISE)); } else { - // NOTE: gc_block.values.xyz is returned from mc_probe_cycle with the updated position value. So + // NOTE: gc_block.values.xyza is returned from mc_probe_cycle with the updated position value. So // upon a successful probing cycle, the machine position and the returned value should be the same. #ifndef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES pl_data->condition |= PL_COND_FLAG_NO_FEED_OVERRIDE; #endif - gc_update_pos = mc_probe_cycle(gc_block.values.xyz, pl_data, gc_parser_flags); + gc_update_pos = mc_probe_cycle(gc_block.values.xyza, pl_data, gc_parser_flags); } // As far as the parser is concerned, the position is now == target. In reality the // motion control system might still be processing the action and the real tool position // in any intermediate location. if (gc_update_pos == GC_UPDATE_POS_TARGET) { - memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc_state.position[] = gc_block.values.xyz[] + memcpy(gc_state.position, gc_block.values.xyza, sizeof(gc_block.values.xyza)); // gc_state.position[] = gc_block.values.xyza[] } else if (gc_update_pos == GC_UPDATE_POS_SYSTEM) { gc_sync_position(); // gc_state.position[] = sys_position } // == GC_UPDATE_POS_NONE diff --git a/grbl/gcode.h b/grbl/gcode.h index 6cdc61b..b8163f2 100644 --- a/grbl/gcode.h +++ b/grbl/gcode.h @@ -149,6 +149,7 @@ #define WORD_X 10 #define WORD_Y 11 #define WORD_Z 12 +#define WORD_A 13 // Define g-code parser position updating flags #define GC_UPDATE_POS_TARGET 0 // Must be zero @@ -198,7 +199,7 @@ typedef struct { typedef struct { float f; // Feed - float ijk[3]; // I,J,K Axis arc offsets + float ijk[N_AXIS]; // I,J,K Axis arc offsets uint8_t l; // G10 or canned cycles parameters int32_t n; // Line number float p; // G10 or dwell parameters @@ -206,7 +207,7 @@ typedef struct { float r; // Arc radius float s; // Spindle speed uint8_t t; // Tool selection - float xyz[3]; // X,Y,Z Translational axes + float xyza[N_AXIS]; // X,Y,Z,A Translational axes } gc_values_t; diff --git a/grbl/grbl.h b/grbl/grbl.h index ef1c324..0c6898f 100644 --- a/grbl/grbl.h +++ b/grbl/grbl.h @@ -23,7 +23,7 @@ // Grbl versioning system #define GRBL_VERSION "1.1f" -#define GRBL_VERSION_BUILD "20170131" +#define GRBL_VERSION_BUILD "20171008" // Define standard libraries used by Grbl. #include @@ -75,9 +75,11 @@ #error "USE_SPINDLE_DIR_AS_ENABLE_PIN may only be used with VARIABLE_SPINDLE enabled" #endif +/* #if defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && !defined(CPU_MAP_ATMEGA328P) #error "USE_SPINDLE_DIR_AS_ENABLE_PIN may only be used with a 328p processor" #endif +*/ #if !defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && defined(SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED) #error "SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED may only be used with USE_SPINDLE_DIR_AS_ENABLE_PIN enabled" diff --git a/grbl/jog.c b/grbl/jog.c index 553af77..c0ba594 100644 --- a/grbl/jog.c +++ b/grbl/jog.c @@ -33,11 +33,11 @@ uint8_t jog_execute(plan_line_data_t *pl_data, parser_block_t *gc_block) #endif if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) { - if (system_check_travel_limits(gc_block->values.xyz)) { return(STATUS_TRAVEL_EXCEEDED); } + if (system_check_travel_limits(gc_block->values.xyza)) { return(STATUS_TRAVEL_EXCEEDED); } } // Valid jog command. Plan, set state, and execute. - mc_line(gc_block->values.xyz,pl_data); + mc_line(gc_block->values.xyza,pl_data); if (sys.state == STATE_IDLE) { if (plan_get_current_block() != NULL) { // Check if there is a block to execute. sys.state = STATE_JOG; diff --git a/grbl/limits.c b/grbl/limits.c index d4eeb23..a0e904b 100644 --- a/grbl/limits.c +++ b/grbl/limits.c @@ -158,9 +158,9 @@ void limits_go_home(uint8_t cycle_mask) // Initialize variables used for homing computations. uint8_t n_cycle = (2*N_HOMING_LOCATE_CYCLE+1); - uint32_t step_pin[N_AXIS]; + uint32_t step_pin[N_AXIS]; // Tracks which pins correspond to which axes (reduces calls to get_step_pin_mask()) float target[N_AXIS]; - float max_travel = 0.0; + float max_travel = 0.0; // Maximum travel distance to move searching for limits uint8_t idx; for (idx=0; idxPINMODE_OD2 |= 1<<0; // Bit P2.0 is open drain Step + LPC_PINCON->PINMODE4 &= ~(3<<0); + LPC_PINCON->PINMODE4 |= (2<<0); // P2.0 has no pull up/down resistor + + LPC_PINCON->PINMODE_OD0 |= 1<<5; // Bit P0.5 is open drain Dir + LPC_PINCON->PINMODE0 &= ~(3<<10); + LPC_PINCON->PINMODE0 |= (2<<10); // P0.5 has no pull up/down resistor + + LPC_PINCON->PINMODE_OD0 |= 1<<4; // Bit P0.4 is open drain Enable + LPC_PINCON->PINMODE0 &= ~(3<<8); + LPC_PINCON->PINMODE0 |= (2<<8); // P0.4 has no pull up/down resistor + #endif + + #ifdef OPEN_DRAIN_Y + LPC_PINCON->PINMODE_OD2 |= 1<<1; // Bit P2.1 is open drain Step + LPC_PINCON->PINMODE4 &= ~(3<<2); + LPC_PINCON->PINMODE4 |= (2<<2); // P2.1 has no pull up/down resistor + + LPC_PINCON->PINMODE_OD0 |= 1<<11; // Bit P0.11 is open drain Dir + LPC_PINCON->PINMODE0 &= ~(3<<22); + LPC_PINCON->PINMODE0 |= (2<<22); // P0.11 has no pull up/down resistor + + LPC_PINCON->PINMODE_OD0 |= 1<<10; // Bit P0.10 is open drain Enable + LPC_PINCON->PINMODE0 &= ~(3<<20); + LPC_PINCON->PINMODE0 |= (2<<20); // P0.10 has no pull up/down resistor + #endif + + #ifdef OPEN_DRAIN_Z + LPC_PINCON->PINMODE_OD2 |= 1<<2; // Bit P2.2 is open drain Step + LPC_PINCON->PINMODE4 &= ~(3<<4); + LPC_PINCON->PINMODE4 |= (2<<4); // P2.2 has no pull up/down resistor + + LPC_PINCON->PINMODE_OD0 |= 1<<20; // Bit P0.20 is open drain Dir + LPC_PINCON->PINMODE1 &= ~(3<<8); + LPC_PINCON->PINMODE1 |= (2<<8); // P0.20 has no pull up/down resistor + + LPC_PINCON->PINMODE_OD0 |= 1<<19; // Bit P0.19 is open drain Enable + LPC_PINCON->PINMODE1 &= ~(3<<6); + LPC_PINCON->PINMODE1 |= (2<<6); // P0.19 has no pull up/down resistor + #endif + + #ifdef OPEN_DRAIN_A + LPC_PINCON->PINMODE_OD2 |= 1<<3; // Bit P2.3 is open drain Step + LPC_PINCON->PINMODE4 &= ~(3<<6); + LPC_PINCON->PINMODE4 |= (2<<6); // P2.2 has no pull up/down resistor + + LPC_PINCON->PINMODE_OD0 |= 1<<22; // Bit P0.22 is open drain Dir + LPC_PINCON->PINMODE1 &= ~(3<<12); + LPC_PINCON->PINMODE1 |= (2<<12); // P0.22 has no pull up/down resistor + + LPC_PINCON->PINMODE_OD0 |= 1<<21; // Bit P0.21 is open drain Enable + LPC_PINCON->PINMODE1 &= ~(3<<10); + LPC_PINCON->PINMODE1 |= (2<<10); // P0.21 has no pull up/down resistor + #endif + // Initialize step pulse timing from settings. Here to ensure updating after re-writing. #ifdef STEP_PULSE_DELAY // Set total step pulse time after direction pin set. Ad hoc computation from oscilloscope. @@ -232,9 +294,9 @@ void st_wake_up() #endif // Enable Stepper Driver Interrupt Timer - LPC_TIM1->TCR = 0b10; // reset - LPC_TIM1->MR0 = 4000; // Generate first interrupt soon - LPC_TIM1->TCR = 0b01; // enable + LPC_TIM1->TCR = 0b10; // reset Timer Control (0b10=Reset, 0b01=Enable) + LPC_TIM1->MR0 = 4000; // Generate first interrupt soon (Match Register for TC) + LPC_TIM1->TCR = 0b01; // enable Timer Control (0b10=Reset, 0b01=Enable) } @@ -242,11 +304,11 @@ void st_wake_up() void st_go_idle() { // Disable Stepper Driver Interrupt. Allow Stepper Port Reset Interrupt to finish, if active. - LPC_TIM1->TCR = 0; // Disable Timer1 + LPC_TIM1->TCR = 0; // Disable Timer1 Control (0b10=Reset, 0b01=Enable) busy = false; // Set stepper driver idle state, disabled or enabled, depending on settings and circumstances. - bool pin_state = false; // Keep enabled. + bool pin_state = false; // Stepper is disabled when pin_state is true. Keep enabled by default. if (((settings.stepper_idle_lock_time != 0xff) || sys_rt_exec_alarm || sys.state == STATE_SLEEP) && sys.state != STATE_HOMING) { // Force stepper dwell to lock axes for a defined amount of time to ensure the axes come to a complete // stop and not drift from residual inertial forces at the end of the last movement. @@ -352,7 +414,7 @@ extern "C" void TIMER1_IRQHandler() #endif // Initialize step segment timing per step and load number of steps to execute. - LPC_TIM1->MR0 = st.exec_segment->cycles_per_tick; + LPC_TIM1->MR0 = st.exec_segment->cycles_per_tick; // Set Match Register to wait one tick st.step_count = st.exec_segment->n_step; // NOTE: Can sometimes be zero when moving slow. // If the new segment starts a new planner block, initialize stepper variables and counters. // NOTE: When the segment data index changes, this indicates a new planner block. @@ -370,6 +432,9 @@ extern "C" void TIMER1_IRQHandler() st.steps[X_AXIS] = st.exec_block->steps[X_AXIS] >> st.exec_segment->amass_level; st.steps[Y_AXIS] = st.exec_block->steps[Y_AXIS] >> st.exec_segment->amass_level; st.steps[Z_AXIS] = st.exec_block->steps[Z_AXIS] >> st.exec_segment->amass_level; + st.steps[A_AXIS] = st.exec_block->steps[A_AXIS] >> st.exec_segment->amass_level; + //st.steps[B_AXIS] = st.exec_block->steps[B_AXIS] >> st.exec_segment->amass_level; + //st.steps[C_AXIS] = st.exec_block->steps[C_AXIS] >> st.exec_segment->amass_level; #endif #ifdef VARIABLE_SPINDLE @@ -433,6 +498,41 @@ extern "C" void TIMER1_IRQHandler() if (st.exec_block->direction_bits & (1<steps[A_AXIS]; + #endif + if (st.counter_a > st.exec_block->step_event_count) { + st.step_outbits |= (1<step_event_count; + if (st.exec_block->direction_bits & (1<steps[B_AXIS]; + #endif + if (st.counter_b > st.exec_block->step_event_count) { + st.step_outbits |= (1<step_event_count; + if (st.exec_block->direction_bits & (1<steps[C_AXIS]; + #endif + if (st.counter_c > st.exec_block->step_event_count) { + st.step_outbits |= (1<step_event_count; + if (st.exec_block->direction_bits & (1<TCR = 0; // disable - LPC_TIM1->CTCR = 0; // timer mode - LPC_TIM1->PR = 0; // no prescale - LPC_TIM1->MCR = 0b011; // MR0: !stop, reset, interrupt - LPC_TIM1->CCR = 0; // no capture - LPC_TIM1->EMR = 0; // no external match + LPC_TIM1->TCR = 0; // disable Timer Control (0b10=Reset, 0b01=Enable) + LPC_TIM1->CTCR = 0; // Count Control (0=TimerMode, 1-3=EdgeCounterMode) + LPC_TIM1->PR = 0; // no Prescale (TC increments every PR+1 clocks) + LPC_TIM1->MCR = 0b011; // Match Control (0b001=InterruptEnbl, 0b010=Reset_Enbl, 0b100=Stop_Enbl) + LPC_TIM1->CCR = 0; // no Capture Control actions + LPC_TIM1->EMR = 0; // no External Match (controls external match pins) NVIC_EnableIRQ(TIMER1_IRQn); // Enable Stepper Driver Interrupt } @@ -676,49 +776,49 @@ void st_prep_buffer() } else { prep.current_speed = sqrt(pl_block->entry_speed_sqr); } - + #ifdef VARIABLE_SPINDLE // Setup laser mode variables. PWM rate adjusted motions will always complete a motion with the - // spindle off. + // spindle off. st_prep_block->is_pwm_rate_adjusted = false; if (settings.flags & BITFLAG_LASER_MODE) { - if (pl_block->condition & PL_COND_FLAG_SPINDLE_CCW) { + if (pl_block->condition & PL_COND_FLAG_SPINDLE_CCW) { // Pre-compute inverse programmed rate to speed up PWM updating per step segment. prep.inv_rate = 1.0/pl_block->programmed_rate; - st_prep_block->is_pwm_rate_adjusted = true; + st_prep_block->is_pwm_rate_adjusted = true; } } #endif } - /* --------------------------------------------------------------------------------- - Compute the velocity profile of a new planner block based on its entry and exit - speeds, or recompute the profile of a partially-completed planner block if the - planner has updated it. For a commanded forced-deceleration, such as from a feed - hold, override the planner velocities and decelerate to the target exit speed. - */ - prep.mm_complete = 0.0; // Default velocity profile complete at 0.0mm from end of block. - float inv_2_accel = 0.5/pl_block->acceleration; - if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) { // [Forced Deceleration to Zero Velocity] - // Compute velocity profile parameters for a feed hold in-progress. This profile overrides - // the planner block profile, enforcing a deceleration to zero speed. - prep.ramp_type = RAMP_DECEL; - // Compute decelerate distance relative to end of block. - float decel_dist = pl_block->millimeters - inv_2_accel*pl_block->entry_speed_sqr; - if (decel_dist < 0.0) { - // Deceleration through entire planner block. End of feed hold is not in this block. - prep.exit_speed = sqrt(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters); - } else { - prep.mm_complete = decel_dist; // End of feed hold. - prep.exit_speed = 0.0; - } - } else { // [Normal Operation] - // Compute or recompute velocity profile parameters of the prepped planner block. - prep.ramp_type = RAMP_ACCEL; // Initialize as acceleration ramp. - prep.accelerate_until = pl_block->millimeters; - - float exit_speed_sqr; - float nominal_speed; + /* --------------------------------------------------------------------------------- + Compute the velocity profile of a new planner block based on its entry and exit + speeds, or recompute the profile of a partially-completed planner block if the + planner has updated it. For a commanded forced-deceleration, such as from a feed + hold, override the planner velocities and decelerate to the target exit speed. + */ + prep.mm_complete = 0.0; // Default velocity profile complete at 0.0mm from end of block. + float inv_2_accel = 0.5/pl_block->acceleration; + if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) { // [Forced Deceleration to Zero Velocity] + // Compute velocity profile parameters for a feed hold in-progress. This profile overrides + // the planner block profile, enforcing a deceleration to zero speed. + prep.ramp_type = RAMP_DECEL; + // Compute decelerate distance relative to end of block. + float decel_dist = pl_block->millimeters - inv_2_accel*pl_block->entry_speed_sqr; + if (decel_dist < 0.0) { + // Deceleration through entire planner block. End of feed hold is not in this block. + prep.exit_speed = sqrt(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters); + } else { + prep.mm_complete = decel_dist; // End of feed hold. + prep.exit_speed = 0.0; + } + } else { // [Normal Operation] + // Compute or recompute velocity profile parameters of the prepped planner block. + prep.ramp_type = RAMP_ACCEL; // Initialize as acceleration ramp. + prep.accelerate_until = pl_block->millimeters; + + float exit_speed_sqr; + float nominal_speed; if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) { prep.exit_speed = exit_speed_sqr = 0.0; // Enforce stop at end of system motion. } else { @@ -727,9 +827,9 @@ void st_prep_buffer() } nominal_speed = plan_compute_profile_nominal_speed(pl_block); - float nominal_speed_sqr = nominal_speed*nominal_speed; - float intersect_distance = - 0.5*(pl_block->millimeters+inv_2_accel*(pl_block->entry_speed_sqr-exit_speed_sqr)); + float nominal_speed_sqr = nominal_speed*nominal_speed; + float intersect_distance = + 0.5*(pl_block->millimeters+inv_2_accel*(pl_block->entry_speed_sqr-exit_speed_sqr)); if (pl_block->entry_speed_sqr > nominal_speed_sqr) { // Only occurs during override reductions. prep.accelerate_until = pl_block->millimeters - inv_2_accel*(pl_block->entry_speed_sqr-nominal_speed_sqr); @@ -752,41 +852,41 @@ void st_prep_buffer() prep.maximum_speed = nominal_speed; prep.ramp_type = RAMP_DECEL_OVERRIDE; } - } else if (intersect_distance > 0.0) { - if (intersect_distance < pl_block->millimeters) { // Either trapezoid or triangle types - // NOTE: For acceleration-cruise and cruise-only types, following calculation will be 0.0. - prep.decelerate_after = inv_2_accel*(nominal_speed_sqr-exit_speed_sqr); - if (prep.decelerate_after < intersect_distance) { // Trapezoid type - prep.maximum_speed = nominal_speed; - if (pl_block->entry_speed_sqr == nominal_speed_sqr) { - // Cruise-deceleration or cruise-only type. - prep.ramp_type = RAMP_CRUISE; - } else { - // Full-trapezoid or acceleration-cruise types - prep.accelerate_until -= inv_2_accel*(nominal_speed_sqr-pl_block->entry_speed_sqr); - } - } else { // Triangle type - prep.accelerate_until = intersect_distance; - prep.decelerate_after = intersect_distance; - prep.maximum_speed = sqrt(2.0*pl_block->acceleration*intersect_distance+exit_speed_sqr); - } - } else { // Deceleration-only type + } else if (intersect_distance > 0.0) { + if (intersect_distance < pl_block->millimeters) { // Either trapezoid or triangle types + // NOTE: For acceleration-cruise and cruise-only types, following calculation will be 0.0. + prep.decelerate_after = inv_2_accel*(nominal_speed_sqr-exit_speed_sqr); + if (prep.decelerate_after < intersect_distance) { // Trapezoid type + prep.maximum_speed = nominal_speed; + if (pl_block->entry_speed_sqr == nominal_speed_sqr) { + // Cruise-deceleration or cruise-only type. + prep.ramp_type = RAMP_CRUISE; + } else { + // Full-trapezoid or acceleration-cruise types + prep.accelerate_until -= inv_2_accel*(nominal_speed_sqr-pl_block->entry_speed_sqr); + } + } else { // Triangle type + prep.accelerate_until = intersect_distance; + prep.decelerate_after = intersect_distance; + prep.maximum_speed = sqrt(2.0*pl_block->acceleration*intersect_distance+exit_speed_sqr); + } + } else { // Deceleration-only type prep.ramp_type = RAMP_DECEL; // prep.decelerate_after = pl_block->millimeters; // prep.maximum_speed = prep.current_speed; - } - } else { // Acceleration-only type - prep.accelerate_until = 0.0; - // prep.decelerate_after = 0.0; - prep.maximum_speed = prep.exit_speed; - } - } - + } + } else { // Acceleration-only type + prep.accelerate_until = 0.0; + // prep.decelerate_after = 0.0; + prep.maximum_speed = prep.exit_speed; + } + } + #ifdef VARIABLE_SPINDLE bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); // Force update whenever updating block. #endif } - + // Initialize new segment segment_t *prep_segment = &segment_buffer[segment_buffer_head]; @@ -896,16 +996,16 @@ void st_prep_buffer() /* ----------------------------------------------------------------------------------- Compute spindle speed PWM output for step segment */ - + if (st_prep_block->is_pwm_rate_adjusted || (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_PWM)) { if (pl_block->condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)) { float rpm = pl_block->spindle_speed; - // NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate. + // NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate. if (st_prep_block->is_pwm_rate_adjusted) { rpm *= (prep.current_speed * prep.inv_rate); } // If current_speed is zero, then may need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE) // but this would be instantaneous only and during a motion. May not matter at all. prep.current_spindle_pwm = spindle_compute_pwm_value(rpm); - } else { + } else { sys.spindle_speed = 0.0; prep.current_spindle_pwm = spindle_pwm_off_value; } @@ -914,7 +1014,7 @@ void st_prep_buffer() prep_segment->spindle_pwm = prep.current_spindle_pwm; // Reload segment PWM value #endif - + /* ----------------------------------------------------------------------------------- Compute segment step rate, steps to execute, and apply necessary rate corrections. NOTE: Steps are computed by direct scalar conversion of the millimeter distance diff --git a/grbl/system.c b/grbl/system.c index 413aa7b..84ca695 100644 --- a/grbl/system.c +++ b/grbl/system.c @@ -23,14 +23,15 @@ void system_init() { + // Configure user control pins (for cycle start, reset, feed hold, etc.) CONTROL_DDR &= ~(CONTROL_MASK); // Configure as input pins #ifdef DISABLE_CONTROL_PIN_PULL_UP CONTROL_PORT &= ~(CONTROL_MASK); // Normal low operation. Requires external pull-down. #else - CONTROL_PORT |= CONTROL_MASK; // Enable internal pull-up resistors. Normal high operation. + CONTROL_PORT |= CONTROL_MASK; // Enable internal pull-up resistors. Normal high operation. #endif - CONTROL_PCMSK |= CONTROL_MASK; // Enable specific pins of the Pin Change Interrupt - PCICR |= (1 << CONTROL_INT); // Enable Pin Change Interrupt + CONTROL_PCMSK |= CONTROL_MASK; // Enable specific pins of the Pin Change Interrupt + PCICR |= (1 << CONTROL_INT); // Enable Pin Change Interrupt } @@ -40,7 +41,7 @@ void system_init() uint8_t system_control_get_state() { uint8_t control_state = 0; - uint8_t pin = (CONTROL_PIN & CONTROL_MASK); + uint32_t pin = (CONTROL_PIN & CONTROL_MASK); #ifdef INVERT_CONTROL_PIN_MASK pin ^= INVERT_CONTROL_PIN_MASK; #endif @@ -185,6 +186,9 @@ uint8_t system_execute_line(char *line) case 'X': mc_homing_cycle(HOMING_CYCLE_X); break; case 'Y': mc_homing_cycle(HOMING_CYCLE_Y); break; case 'Z': mc_homing_cycle(HOMING_CYCLE_Z); break; + case 'A': mc_homing_cycle(HOMING_CYCLE_A); break; + //case 'B': mc_homing_cycle(HOMING_CYCLE_B); break; + //case 'C': mc_homing_cycle(HOMING_CYCLE_C); break; default: return(STATUS_INVALID_STATEMENT); } #endif @@ -192,7 +196,7 @@ uint8_t system_execute_line(char *line) if (!sys.abort) { // Execute startup scripts after successful homing. sys.state = STATE_IDLE; // Set to IDLE when complete. st_go_idle(); // Set steppers to the settings idle state before returning. - if (line[2] == 0) { system_execute_startup(line); } + if (line[2] == 0) { system_execute_startup(line); } // Execute startup script again. } break; case 'S' : // Puts Grbl to sleep [IDLE/ALARM] @@ -342,7 +346,11 @@ uint8_t system_check_travel_limits(float *target) } #else // NOTE: max_travel is stored as negative - if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { return(true); } + #ifdef HOMING_FORCE_POSITIVE_SPACE + if (target[idx] < 0 || target[idx] > -settings.max_travel[idx]) { return(true); } + #else + if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { return(true); } + #endif #endif } return(false);