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/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 53dad9d..ed7a45f 100644 --- a/grbl/config.h +++ b/grbl/config.h @@ -38,13 +38,15 @@ //#define CPU_MAP_MKS_SBASE // MKS SBASE Board (NXP LPC1768 MCU) //#define CPU_MAP_AZTEEG_X5 // Azteeg X5 Board (NXP LPC1769 MCU) -// Force Spincle PWM Pin 2.4 (default is P2.5) +// 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 @@ -111,19 +113,19 @@ // 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< 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_DDR DDRB #define SPINDLE_PWM_PORT PORTB - #define SPINDLE_PWM_BIT 3 // Uno Digital Pin 11 + #define SPINDLE_PWM_BIT 3 // Uno Digital Pin 11 -#endif +#endif // end of CPU_MAP_ATMEGA328P #ifdef CPU_MAP_SMOOTHIEBOARD // (Smoothieboards) @@ -212,7 +212,7 @@ #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 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. @@ -264,11 +264,11 @@ #endif //#define SPINDLE_PWM_OFF_VALUE 0 // Defined in config.h #define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE) - #define SPINDLE_TCCRA_REGISTER TCCR2A - #define SPINDLE_TCCRB_REGISTER TCCR2B + #define SPINDLE_TCCRA_REGISTER TCCR2A + #define SPINDLE_TCCRB_REGISTER TCCR2B #define SPINDLE_OCR_REGISTER OCR2A - #define SPINDLE_COMB_BIT COM2A1 -#endif + #define SPINDLE_COMB_BIT COM2A1 +#endif // end of CPU_MAP_SMOOTHIEBOARD #ifdef CPU_MAP_C3D_REMIX // (Cohesion3D Remix Boards) @@ -311,7 +311,7 @@ #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 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<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 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<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 Z_LIMIT_BIT 28 // Z-MIN=28, Z-MAX=29 #define A_LIMIT_BIT 29 // reuse p1.29 #define LIMIT_MASK ((1<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 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<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 @@ -672,8 +678,8 @@ // The LPC17xx has 6 PWM channels. Each channel has 2 pins. It can drive both pins simultaneously to the same value. // // PWM Channel PWM1_CH1 PWM1_CH2 PWM1_CH3 PWM1_CH4 PWM1_CH5 PWM1_CH6 - // Primary pin P1.18 P1.20 P1.21 P1.23 P1.24 P1.26 - // Secondary pin P2.0 P2.1 P2.2 P2.3 P2.4 P2.5 + // Primary pin P1.18 P1.20 P1.21 P1.23 P1.24 P1.26 + // Secondary pin P2.0 P2.1 P2.2 P2.3 P2.4 P2.5 #ifdef SPINDLE_PWM_PIN_2_4 #define SPINDLE_PWM_CHANNEL PWM1_CH5 // MOSFET3 (P2.4) #else @@ -692,11 +698,11 @@ #endif //#define SPINDLE_PWM_OFF_VALUE 0 // Defined in config.h #define SPINDLE_PWM_RANGE (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE) - #define SPINDLE_TCCRA_REGISTER TCCR2A - #define SPINDLE_TCCRB_REGISTER TCCR2B + #define SPINDLE_TCCRA_REGISTER TCCR2A + #define SPINDLE_TCCRB_REGISTER TCCR2B #define SPINDLE_OCR_REGISTER OCR2A - #define SPINDLE_COMB_BIT COM2A1 -#endif + #define SPINDLE_COMB_BIT COM2A1 +#endif // end of CPU_MAP_AZTEEG_X5 /* diff --git a/grbl/defaults.h b/grbl/defaults.h index f58d000..ffacec5 100644 --- a/grbl/defaults.h +++ b/grbl/defaults.h @@ -29,54 +29,57 @@ #ifdef DEFAULTS_GENERIC // Grbl generic default settings. Should work across different machines. - #define DEFAULT_X_STEPS_PER_MM 250.0 - #define DEFAULT_Y_STEPS_PER_MM 250.0 - #define DEFAULT_Z_STEPS_PER_MM 250.0 - #define DEFAULT_A_STEPS_PER_MM 160.0 - #define DEFAULT_X_MAX_RATE 500.0 // mm/min - #define DEFAULT_Y_MAX_RATE 500.0 // mm/min - #define DEFAULT_Z_MAX_RATE 500.0 // mm/min - #define DEFAULT_A_MAX_RATE 500.0 // mm/min - #define DEFAULT_X_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2 - #define DEFAULT_Y_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2 - #define DEFAULT_Z_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2 - #define DEFAULT_A_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2 - #define DEFAULT_X_CURRENT 0.6 // amps - #define DEFAULT_Y_CURRENT 0.6 // amps - #define DEFAULT_Z_CURRENT 0.0 // amps - #define DEFAULT_A_CURRENT 0.0 // amps - #define DEFAULT_X_MAX_TRAVEL 200.0 // mm NOTE: Must be a positive value. - #define DEFAULT_Y_MAX_TRAVEL 200.0 // mm NOTE: Must be a positive value. - #define DEFAULT_Z_MAX_TRAVEL 200.0 // mm NOTE: Must be a positive value. - #define DEFAULT_A_MAX_TRAVEL 1.0 // mm NOTE: Must be a positive value. - #define DEFAULT_SPINDLE_PWM_FREQ 5000 // Hz - #define DEFAULT_SPINDLE_PWM_OFF_VALUE 0 // % - #define DEFAULT_SPINDLE_PWM_MIN_VALUE 1 // % - #define DEFAULT_SPINDLE_PWM_MAX_VALUE 100 // % - #define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm (S-value) - #define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm (S-value) - #define DEFAULT_STEP_PULSE_MICROSECONDS 10 - #define DEFAULT_STEPPING_INVERT_MASK 0 - #define DEFAULT_DIRECTION_INVERT_MASK 0 - #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled) - #define DEFAULT_STATUS_REPORT_MASK 0 // WPos enabled - #define DEFAULT_JUNCTION_DEVIATION 0.01 // mm - #define DEFAULT_ARC_TOLERANCE 0.002 // mm - #define DEFAULT_REPORT_INCHES 0 // false - #define DEFAULT_INVERT_ST_ENABLE 0 // false - #define DEFAULT_INVERT_LIMIT_PINS 0 // false - #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false - #define DEFAULT_HARD_LIMIT_ENABLE 0 // false - #define DEFAULT_INVERT_PROBE_PIN 0 // false - #define DEFAULT_LASER_MODE 0 // false - #define DEFAULT_HOMING_ENABLE 0 // false - #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir - #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min - #define DEFAULT_HOMING_SEEK_RATE 500.0 // mm/min - #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k) - #define DEFAULT_HOMING_PULLOFF 1.0 // mm + // See https://github.com/gnea/grbl/wiki/Grbl-v1.1-Configuration for setting descriptions. + #define DEFAULT_X_STEPS_PER_MM 250.0 // $100 steps (X steps per mm) + #define DEFAULT_Y_STEPS_PER_MM 250.0 // $101 steps (Y steps per mm) + #define DEFAULT_Z_STEPS_PER_MM 250.0 // $102 steps (Z steps per mm) + #define DEFAULT_A_STEPS_PER_MM 160.0 // $103 steps (A steps per mm) + #define DEFAULT_X_MAX_RATE 500.0 // $110 mm/min (X max speed) + #define DEFAULT_Y_MAX_RATE 500.0 // $111 mm/min (Y max speed) + #define DEFAULT_Z_MAX_RATE 500.0 // $112 mm/min (Z max speed) + #define DEFAULT_A_MAX_RATE 500.0 // $113 mm/min (A max speed) + #define DEFAULT_X_ACCELERATION (10.0*60*60)// $120 mm/min^2 (X max acceleration) + #define DEFAULT_Y_ACCELERATION (10.0*60*60)// $121 mm/min^2 (Y max acceleration) + #define DEFAULT_Z_ACCELERATION (10.0*60*60)// $122 mm/min^2 (Z max acceleration) + #define DEFAULT_A_ACCELERATION (10.0*60*60)// $123 mm/min^2 (A max acceleration) + #define DEFAULT_X_MAX_TRAVEL 200.0 // $130 mm (X max travel; must be positive) + #define DEFAULT_Y_MAX_TRAVEL 200.0 // $131 mm (Y max travel; must be positive) + #define DEFAULT_Z_MAX_TRAVEL 200.0 // $132 mm (Z max travel; must be positive) + #define DEFAULT_A_MAX_TRAVEL 1.0 // $133 mm (A max travel; must be positive) + #define DEFAULT_X_CURRENT 0.6 // $140 amps (X stepper current [disabled]) + #define DEFAULT_Y_CURRENT 0.6 // $141 amps (Y stepper current [disabled]) + #define DEFAULT_Z_CURRENT 0.0 // $142 amps (Z stepper current [disabled]) + #define DEFAULT_A_CURRENT 0.0 // $143 amps (A stepper current [disabled]) + + #define DEFAULT_STEP_PULSE_MICROSECONDS 10 // $0 usec (stepper pulse time) + #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // $1 msec (0-254, 255 keeps steppers enabled) + #define DEFAULT_STEPPING_INVERT_MASK 0 // $2 ZYX (e.g., 0x5 inverts Z and X stepper pulses) + #define DEFAULT_DIRECTION_INVERT_MASK 0 // $3 ZYX (e.g., 0x2 inverts Y stepper direction) + #define DEFAULT_INVERT_ST_ENABLE 0 // $4 bool (inverts stepper enable pin) + #define DEFAULT_INVERT_LIMIT_PINS 0 // $5 bool (inverts limit switches to trigger on high) + #define DEFAULT_INVERT_PROBE_PIN 0 // $6 bool (inverts probe to trigger on high) + #define DEFAULT_STATUS_REPORT_MASK 0 // $10 bits (Reports: [0=WPos or 1=MPos] and [2=Buffer]) + #define DEFAULT_JUNCTION_DEVIATION 0.01 // $11 mm (determines machine speed through corners) + #define DEFAULT_ARC_TOLERANCE 0.002 // $12 mm (error tolerance on arcs/cicles) + #define DEFAULT_REPORT_INCHES 0 // $13 bool (sets position reporting to inches) + #define DEFAULT_SOFT_LIMIT_ENABLE 0 // $20 bool (prevents moves outside *_MAX_TRAVEL; requires $23=1) + #define DEFAULT_HARD_LIMIT_ENABLE 0 // $21 bool ([ignored] stops moving when limit switches triggered) + #define DEFAULT_HOMING_ENABLE 0 // $22 bool (enables homing on startup) + #define DEFAULT_HOMING_DIR_MASK 0 // $23 ZYX (e.g., 0x3 reverses XY homing to negative direction) + #define DEFAULT_HOMING_FEED_RATE 25.0 // $24 mm/min (homing precision location speed) + #define DEFAULT_HOMING_SEEK_RATE 500.0 // $25 mm/min (homing search speed) + #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // $26 msec (homing switch debounce: 0-65k) + #define DEFAULT_HOMING_PULLOFF 1.0 // $27 mm (retracts this far from homing switch) + #define DEFAULT_SPINDLE_RPM_MAX 1000.0 // $30 RPM (spindle speed for max 5V PWM output) + #define DEFAULT_SPINDLE_RPM_MIN 0.0 // $31 RPM (spindle speed for min 20mV PWM output) + #define DEFAULT_LASER_MODE 0 // $32 bool (adjusts spindle power with speed for lasers) + #define DEFAULT_SPINDLE_PWM_FREQ 5000 // $33 Hz (PWM frequency for spindle) + #define DEFAULT_SPINDLE_PWM_OFF_VALUE 0 // $34 % (% of PWM when spindle is off) + #define DEFAULT_SPINDLE_PWM_MIN_VALUE 1 // $35 % (% of PWM when spindle is at lowest setting) + #define DEFAULT_SPINDLE_PWM_MAX_VALUE 100 // $36 % (% of PWM when spindle is at highest setting) + // Up to 4 HOMING_CYCLE_x can be defined (0-3), specifying which axes are homed and in which order #define HOMING_CYCLE_0 ((1<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) } @@ -245,11 +245,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. @@ -355,7 +355,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. @@ -503,7 +503,7 @@ extern "C" void TIMER1_IRQHandler() cause issues at high step rates if another high frequency asynchronous interrupt is added to Grbl. */ -/* Not ported; the main ISR assumes short pulse widths and handles it. Stepper drivers with +/* Not ported; the main ISR assumes short pulse widths and handles it. Stepper drivers with long pulse widths may need this instead if they cause the main ISR to consume too much time. // This interrupt is enabled by ISR_TIMER1_COMPAREA when it sets the motor port bits to execute // a step. This ISR resets the motor port after a short period (settings.pulse_microseconds) @@ -570,17 +570,17 @@ void st_reset() void stepper_init() { // Configure step and direction interface pins - STEP_DDR |= STEP_MASK; - STEPPERS_DISABLE_DDR |= STEPPERS_DISABLE_MASK; - DIRECTION_DDR |= DIRECTION_MASK; + STEP_DDR |= STEP_MASK; // Set selected stepper step pins as outputs + STEPPERS_DISABLE_DDR |= STEPPERS_DISABLE_MASK; // Set selected stepper disable pins as outputs + DIRECTION_DDR |= DIRECTION_MASK; // Set selected stepper direction pins as outputs // Configure Timer 1: Stepper Driver Interrupt - LPC_TIM1->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 } @@ -717,49 +717,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; + /* --------------------------------------------------------------------------------- + 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; + 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 { @@ -768,9 +768,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); @@ -793,41 +793,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]; @@ -937,16 +937,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; } @@ -955,7 +955,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 457917b..01e458b 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 } @@ -195,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]