From 60fdb7da73ce32d6c73b5fbbbc1b736ab6920722 Mon Sep 17 00:00:00 2001 From: Scott Smith Date: Fri, 8 Dec 2017 12:12:44 -0800 Subject: [PATCH 1/9] Update TimerOne for Teensy --- cnc_ctrl_v1/TimerOne.cpp | 213 ++-------- cnc_ctrl_v1/TimerOne.h | 519 +++++++++++++++++++++--- cnc_ctrl_v1/config/known_16bit_timers.h | 153 +++++++ cnc_ctrl_v1/utility/direct_pin_read.h | 2 +- 4 files changed, 650 insertions(+), 237 deletions(-) mode change 100644 => 100755 cnc_ctrl_v1/TimerOne.cpp mode change 100644 => 100755 cnc_ctrl_v1/TimerOne.h create mode 100755 cnc_ctrl_v1/config/known_16bit_timers.h mode change 100644 => 100755 cnc_ctrl_v1/utility/direct_pin_read.h diff --git a/cnc_ctrl_v1/TimerOne.cpp b/cnc_ctrl_v1/TimerOne.cpp old mode 100644 new mode 100755 index efede8d3..7e838d0a --- a/cnc_ctrl_v1/TimerOne.cpp +++ b/cnc_ctrl_v1/TimerOne.cpp @@ -3,207 +3,52 @@ * Original code by Jesse Tane for http://labs.ideo.com August 2008 * Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support * Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop - * Modified June 2011 by Lex Talionis to add a function to read the timer - * Modified Oct 2011 by Andrew Richards to avoid certain problems: - * - Add (long) assignments and casts to TimerOne::read() to ensure calculations involving tmp, ICR1 and TCNT1 aren't truncated - * - Ensure 16 bit registers accesses are atomic - run with interrupts disabled when accessing - * - Remove global enable of interrupts (sei())- could be running within an interrupt routine) - * - Disable interrupts whilst TCTN1 == 0. Datasheet vague on this, but experiment shows that overflow interrupt - * flag gets set whilst TCNT1 == 0, resulting in a phantom interrupt. Could just set to 1, but gets inaccurate - * at very short durations - * - startBottom() added to start counter at 0 and handle all interrupt enabling. - * - start() amended to enable interrupts - * - restart() amended to point at startBottom() - * Modiied 7:26 PM Sunday, October 09, 2011 by Lex Talionis - * - renamed start() to resume() to reflect it's actual role - * - renamed startBottom() to start(). This breaks some old code that expects start to continue counting where it left off + * Modified Oct 2009 by Dan Clemens to work with timer1 of the ATMega1280 or Arduino Mega + * Modified April 2012 by Paul Stoffregen + * Modified again, June 2014 by Paul Stoffregen + * Modified July 2017 by Stoyko Dimitrov - added support for ATTiny85 except for the PWM functionality * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This is free software. You can redistribute it and/or modify it under + * the terms of Creative Commons Attribution 3.0 United States License. + * To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/ + * or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * See Google Code project http://code.google.com/p/arduino-timerone/ for latest */ -#ifndef TIMERONE_cpp -#define TIMERONE_cpp #include "TimerOne.h" TimerOne Timer1; // preinstatiate -ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt -{ - Timer1.isrCallback(); -} - - -void TimerOne::initialize(long microseconds) -{ - TCCR1A = 0; // clear control register A - TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm, stop the timer - setPeriod(microseconds); -} - - -void TimerOne::setPeriod(long microseconds) // AR modified for atomic access -{ - - long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2 - if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal - else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8 - else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64 - else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256 - else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024 - else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum - - oldSREG = SREG; - cli(); // Disable interrupts for 16 bit register access - ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode - SREG = oldSREG; - - TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); - TCCR1B |= clockSelectBits; // reset clock select register, and starts the clock -} - -void TimerOne::setPwmDuty(char pin, int duty) -{ - unsigned long dutyCycle = pwmPeriod; - - dutyCycle *= duty; - dutyCycle >>= 10; - - oldSREG = SREG; - cli(); - if(pin == 1 || pin == 9) OCR1A = dutyCycle; - else if(pin == 2 || pin == 10) OCR1B = dutyCycle; - SREG = oldSREG; -} - -void TimerOne::pwm(char pin, int duty, long microseconds) // expects duty cycle to be 10 bit (1024) -{ - if(microseconds > 0) setPeriod(microseconds); - if(pin == 1 || pin == 9) { - DDRB |= _BV(PORTB1); // sets data direction register for pwm output pin - TCCR1A |= _BV(COM1A1); // activates the output pin - } - else if(pin == 2 || pin == 10) { - DDRB |= _BV(PORTB2); - TCCR1A |= _BV(COM1B1); - } - setPwmDuty(pin, duty); - resume(); // Lex - make sure the clock is running. We don't want to restart the count, in case we are starting the second WGM - // and the first one is in the middle of a cycle -} +unsigned short TimerOne::pwmPeriod = 0; +unsigned char TimerOne::clockSelectBits = 0; +void (*TimerOne::isrCallback)() = TimerOne::isrDefaultUnused; -void TimerOne::disablePwm(char pin) +// interrupt service routine that wraps a user defined function supplied by attachInterrupt +#if defined (__AVR_ATtiny85__) +ISR(TIMER1_COMPA_vect) { - if(pin == 1 || pin == 9) TCCR1A &= ~_BV(COM1A1); // clear the bit that enables pwm on PB1 - else if(pin == 2 || pin == 10) TCCR1A &= ~_BV(COM1B1); // clear the bit that enables pwm on PB2 -} - -void TimerOne::attachInterrupt(void (*isr)(), long microseconds) -{ - if(microseconds > 0) setPeriod(microseconds); - isrCallback = isr; // register the user's callback with the real ISR - TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit - // might be running with interrupts disabled (eg inside an ISR), so don't touch the global state -// sei(); - resume(); + Timer1.isrCallback(); } - -void TimerOne::detachInterrupt() +#elif defined(__AVR__) +ISR(TIMER1_OVF_vect) { - TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit - // timer continues to count without calling the isr -} - -void TimerOne::resume() // AR suggested -{ - TCCR1B |= clockSelectBits; + Timer1.isrCallback(); } -void TimerOne::restart() // Depricated - Public interface to start at zero - Lex 10/9/2011 +#elif defined(__arm__) && defined(CORE_TEENSY) +void ftm1_isr(void) { - start(); + uint32_t sc = FTM1_SC; + #ifdef KINETISL + if (sc & 0x80) FTM1_SC = sc; + #else + if (sc & 0x80) FTM1_SC = sc & 0x7F; + #endif + Timer1.isrCallback(); } -void TimerOne::start() // AR addition, renamed by Lex to reflect it's actual role -{ - unsigned int tcnt1; - - TIMSK1 &= ~_BV(TOIE1); // AR added - GTCCR |= _BV(PSRSYNC); // AR added - reset prescaler (NB: shared with all 16 bit timers); - - oldSREG = SREG; // AR - save status register - cli(); // AR - Disable interrupts - TCNT1 = 0; - SREG = oldSREG; // AR - Restore status register - resume(); - do { // Nothing -- wait until timer moved on from zero - otherwise get a phantom interrupt - oldSREG = SREG; - cli(); - tcnt1 = TCNT1; - SREG = oldSREG; - } while (tcnt1==0); - -// TIFR1 = 0xff; // AR - Clear interrupt flags -// TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit -} +#endif -void TimerOne::stop() +void TimerOne::isrDefaultUnused() { - TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits } - -unsigned long TimerOne::read() //returns the value of the timer in microseconds -{ //rember! phase and freq correct mode counts up to then down again - unsigned long tmp; // AR amended to hold more than 65536 (could be nearly double this) - unsigned int tcnt1; // AR added - - oldSREG= SREG; - cli(); - tmp=TCNT1; - SREG = oldSREG; - - char scale=0; - switch (clockSelectBits) - { - case 1:// no prescalse - scale=0; - break; - case 2:// x8 prescale - scale=3; - break; - case 3:// x64 - scale=6; - break; - case 4:// x256 - scale=8; - break; - case 5:// x1024 - scale=10; - break; - } - - do { // Nothing -- max delay here is ~1023 cycles. AR modified - oldSREG = SREG; - cli(); - tcnt1 = TCNT1; - SREG = oldSREG; - } while (tcnt1==tmp); //if the timer has not ticked yet - - //if we are counting down add the top value to how far we have counted down - tmp = ( (tcnt1>tmp) ? (tmp) : (long)(ICR1-tcnt1)+(long)ICR1 ); // AR amended to add casts and reuse previous TCNT1 - return ((tmp*1000L)/(F_CPU /1000L))<. - * - * See Google Code project http://code.google.com/p/arduino-timerone/ for latest */ -#ifndef TIMERONE_h -#define TIMERONE_h -#include -#include +#ifndef TimerOne_h_ +#define TimerOne_h_ + +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +#include "config/known_16bit_timers.h" +#if defined (__AVR_ATtiny85__) +#define TIMER1_RESOLUTION 256UL // Timer1 is 8 bit +#elif defined(__AVR__) +#define TIMER1_RESOLUTION 65536UL // Timer1 is 16 bit +#else +#define TIMER1_RESOLUTION 65536UL // assume 16 bits for non-AVR chips +#endif + +// Placing nearly all the code in this .h file allows the functions to be +// inlined by the compiler. In the very common case with constant values +// the compiler will perform all calculations and simply write constants +// to the hardware registers (for example, setPeriod). -#define RESOLUTION 65536 // Timer1 is 16 bit class TimerOne { + +#if defined (__AVR_ATtiny85__) + public: + //**************************** + // Configuration + //**************************** + void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) { + TCCR1 = _BV(CTC1); //clear timer1 when it matches the value in OCR1C + TIMSK |= _BV(OCIE1A); //enable interrupt when OCR1A matches the timer value + setPeriod(microseconds); + } + void setPeriod(unsigned long microseconds) __attribute__((always_inline)) { + const unsigned long cycles = microseconds * ratio; + if (cycles < TIMER1_RESOLUTION) { + clockSelectBits = _BV(CS10); + pwmPeriod = cycles; + } else + if (cycles < TIMER1_RESOLUTION * 2UL) { + clockSelectBits = _BV(CS11); + pwmPeriod = cycles / 2; + } else + if (cycles < TIMER1_RESOLUTION * 4UL) { + clockSelectBits = _BV(CS11) | _BV(CS10); + pwmPeriod = cycles / 4; + } else + if (cycles < TIMER1_RESOLUTION * 8UL) { + clockSelectBits = _BV(CS12); + pwmPeriod = cycles / 8; + } else + if (cycles < TIMER1_RESOLUTION * 16UL) { + clockSelectBits = _BV(CS12) | _BV(CS10); + pwmPeriod = cycles / 16; + } else + if (cycles < TIMER1_RESOLUTION * 32UL) { + clockSelectBits = _BV(CS12) | _BV(CS11); + pwmPeriod = cycles / 32; + } else + if (cycles < TIMER1_RESOLUTION * 64UL) { + clockSelectBits = _BV(CS12) | _BV(CS11) | _BV(CS10); + pwmPeriod = cycles / 64UL; + } else + if (cycles < TIMER1_RESOLUTION * 128UL) { + clockSelectBits = _BV(CS13); + pwmPeriod = cycles / 128; + } else + if (cycles < TIMER1_RESOLUTION * 256UL) { + clockSelectBits = _BV(CS13) | _BV(CS10); + pwmPeriod = cycles / 256; + } else + if (cycles < TIMER1_RESOLUTION * 512UL) { + clockSelectBits = _BV(CS13) | _BV(CS11); + pwmPeriod = cycles / 512; + } else + if (cycles < TIMER1_RESOLUTION * 1024UL) { + clockSelectBits = _BV(CS13) | _BV(CS11) | _BV(CS10); + pwmPeriod = cycles / 1024; + } else + if (cycles < TIMER1_RESOLUTION * 2048UL) { + clockSelectBits = _BV(CS13) | _BV(CS12); + pwmPeriod = cycles / 2048; + } else + if (cycles < TIMER1_RESOLUTION * 4096UL) { + clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS10); + pwmPeriod = cycles / 4096; + } else + if (cycles < TIMER1_RESOLUTION * 8192UL) { + clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11); + pwmPeriod = cycles / 8192; + } else + if (cycles < TIMER1_RESOLUTION * 16384UL) { + clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11) | _BV(CS10); + pwmPeriod = cycles / 16384; + } else { + clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11) | _BV(CS10); + pwmPeriod = TIMER1_RESOLUTION - 1; + } + OCR1A = pwmPeriod; + OCR1C = pwmPeriod; + TCCR1 = _BV(CTC1) | clockSelectBits; + } + + //**************************** + // Run Control + //**************************** + void start() __attribute__((always_inline)) { + TCCR1 = 0; + TCNT1 = 0; + resume(); + } + void stop() __attribute__((always_inline)) { + TCCR1 = _BV(CTC1); + } + void restart() __attribute__((always_inline)) { + start(); + } + void resume() __attribute__((always_inline)) { + TCCR1 = _BV(CTC1) | clockSelectBits; + } + + //**************************** + // PWM outputs + //**************************** + //Not implemented yet for ATTiny85 + //TO DO + + //**************************** + // Interrupt Function + //**************************** + void attachInterrupt(void (*isr)()) __attribute__((always_inline)) { + isrCallback = isr; + TIMSK |= _BV(OCIE1A); + } + void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) { + if(microseconds > 0) setPeriod(microseconds); + attachInterrupt(isr); + } + void detachInterrupt() __attribute__((always_inline)) { + //TIMSK = 0; // Timer 0 and Timer 1 both use TIMSK register so setting it to 0 will override settings for Timer1 as well + TIMSK &= ~_BV(OCIE1A); + } + static void (*isrCallback)(); + static void isrDefaultUnused(); + + private: + static unsigned short pwmPeriod; + static unsigned char clockSelectBits; + static const byte ratio = (F_CPU)/ ( 1000000 ); + +#elif defined(__AVR__) public: - + //**************************** + // Configuration + //**************************** + void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) { + TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer + TCCR1A = 0; // clear control register A + setPeriod(microseconds); + } + void setPeriod(unsigned long microseconds) __attribute__((always_inline)) { + const unsigned long cycles = (F_CPU / 2000000) * microseconds; + if (cycles < TIMER1_RESOLUTION) { + clockSelectBits = _BV(CS10); + pwmPeriod = cycles; + } else + if (cycles < TIMER1_RESOLUTION * 8) { + clockSelectBits = _BV(CS11); + pwmPeriod = cycles / 8; + } else + if (cycles < TIMER1_RESOLUTION * 64) { + clockSelectBits = _BV(CS11) | _BV(CS10); + pwmPeriod = cycles / 64; + } else + if (cycles < TIMER1_RESOLUTION * 256) { + clockSelectBits = _BV(CS12); + pwmPeriod = cycles / 256; + } else + if (cycles < TIMER1_RESOLUTION * 1024) { + clockSelectBits = _BV(CS12) | _BV(CS10); + pwmPeriod = cycles / 1024; + } else { + clockSelectBits = _BV(CS12) | _BV(CS10); + pwmPeriod = TIMER1_RESOLUTION - 1; + } + ICR1 = pwmPeriod; + TCCR1B = _BV(WGM13) | clockSelectBits; + } + + //**************************** + // Run Control + //**************************** + void start() __attribute__((always_inline)) { + TCCR1B = 0; + TCNT1 = 0; // TODO: does this cause an undesired interrupt? + resume(); + } + void stop() __attribute__((always_inline)) { + TCCR1B = _BV(WGM13); + } + void restart() __attribute__((always_inline)) { + start(); + } + void resume() __attribute__((always_inline)) { + TCCR1B = _BV(WGM13) | clockSelectBits; + } + + //**************************** + // PWM outputs + //**************************** + void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) { + unsigned long dutyCycle = pwmPeriod; + dutyCycle *= duty; + dutyCycle >>= 10; + if (pin == TIMER1_A_PIN) OCR1A = dutyCycle; + #ifdef TIMER1_B_PIN + else if (pin == TIMER1_B_PIN) OCR1B = dutyCycle; + #endif + #ifdef TIMER1_C_PIN + else if (pin == TIMER1_C_PIN) OCR1C = dutyCycle; + #endif + } + void pwm(char pin, unsigned int duty) __attribute__((always_inline)) { + if (pin == TIMER1_A_PIN) { pinMode(TIMER1_A_PIN, OUTPUT); TCCR1A |= _BV(COM1A1); } + #ifdef TIMER1_B_PIN + else if (pin == TIMER1_B_PIN) { pinMode(TIMER1_B_PIN, OUTPUT); TCCR1A |= _BV(COM1B1); } + #endif + #ifdef TIMER1_C_PIN + else if (pin == TIMER1_C_PIN) { pinMode(TIMER1_C_PIN, OUTPUT); TCCR1A |= _BV(COM1C1); } + #endif + setPwmDuty(pin, duty); + TCCR1B = _BV(WGM13) | clockSelectBits; + } + void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) { + if (microseconds > 0) setPeriod(microseconds); + pwm(pin, duty); + } + void disablePwm(char pin) __attribute__((always_inline)) { + if (pin == TIMER1_A_PIN) TCCR1A &= ~_BV(COM1A1); + #ifdef TIMER1_B_PIN + else if (pin == TIMER1_B_PIN) TCCR1A &= ~_BV(COM1B1); + #endif + #ifdef TIMER1_C_PIN + else if (pin == TIMER1_C_PIN) TCCR1A &= ~_BV(COM1C1); + #endif + } + + //**************************** + // Interrupt Function + //**************************** + void attachInterrupt(void (*isr)()) __attribute__((always_inline)) { + isrCallback = isr; + TIMSK1 = _BV(TOIE1); + } + void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) { + if(microseconds > 0) setPeriod(microseconds); + attachInterrupt(isr); + } + void detachInterrupt() __attribute__((always_inline)) { + TIMSK1 = 0; + } + static void (*isrCallback)(); + static void isrDefaultUnused(); + + private: // properties - unsigned int pwmPeriod; - unsigned char clockSelectBits; - char oldSREG; // To hold Status Register while ints disabled - - // methods - void initialize(long microseconds=1000000); - void start(); - void stop(); - void restart(); - void resume(); - unsigned long read(); - void pwm(char pin, int duty, long microseconds=-1); - void disablePwm(char pin); - void attachInterrupt(void (*isr)(), long microseconds=-1); - void detachInterrupt(); - void setPeriod(long microseconds); - void setPwmDuty(char pin, int duty); - void (*isrCallback)(); + static unsigned short pwmPeriod; + static unsigned char clockSelectBits; + + + + + + +#elif defined(__arm__) && defined(CORE_TEENSY) + +#if defined(KINETISK) +#define F_TIMER F_BUS +#elif defined(KINETISL) +#define F_TIMER (F_PLL/2) +#endif + + public: + //**************************** + // Configuration + //**************************** + void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) { + setPeriod(microseconds); + } + void setPeriod(unsigned long microseconds) __attribute__((always_inline)) { + const unsigned long cycles = (F_TIMER / 2000000) * microseconds; + // A much faster if-else + // This is like a binary serch tree and no more than 3 conditions are evaluated. + // I haven't checked if this becomes significantly longer ASM than the simple ladder. + // It looks very similar to the ladder tho: same # of if's and else's + + /* + // This code does not work properly in all cases :( + // https://github.com/PaulStoffregen/TimerOne/issues/17 + if (cycles < TIMER1_RESOLUTION * 16) { + if (cycles < TIMER1_RESOLUTION * 4) { + if (cycles < TIMER1_RESOLUTION) { + clockSelectBits = 0; + pwmPeriod = cycles; + }else{ + clockSelectBits = 1; + pwmPeriod = cycles >> 1; + } + }else{ + if (cycles < TIMER1_RESOLUTION * 8) { + clockSelectBits = 3; + pwmPeriod = cycles >> 3; + }else{ + clockSelectBits = 4; + pwmPeriod = cycles >> 4; + } + } + }else{ + if (cycles > TIMER1_RESOLUTION * 64) { + if (cycles > TIMER1_RESOLUTION * 128) { + clockSelectBits = 7; + pwmPeriod = TIMER1_RESOLUTION - 1; + }else{ + clockSelectBits = 7; + pwmPeriod = cycles >> 7; + } + } + else{ + if (cycles > TIMER1_RESOLUTION * 32) { + clockSelectBits = 6; + pwmPeriod = cycles >> 6; + }else{ + clockSelectBits = 5; + pwmPeriod = cycles >> 5; + } + } + } + */ + if (cycles < TIMER1_RESOLUTION) { + clockSelectBits = 0; + pwmPeriod = cycles; + } else + if (cycles < TIMER1_RESOLUTION * 2) { + clockSelectBits = 1; + pwmPeriod = cycles >> 1; + } else + if (cycles < TIMER1_RESOLUTION * 4) { + clockSelectBits = 2; + pwmPeriod = cycles >> 2; + } else + if (cycles < TIMER1_RESOLUTION * 8) { + clockSelectBits = 3; + pwmPeriod = cycles >> 3; + } else + if (cycles < TIMER1_RESOLUTION * 16) { + clockSelectBits = 4; + pwmPeriod = cycles >> 4; + } else + if (cycles < TIMER1_RESOLUTION * 32) { + clockSelectBits = 5; + pwmPeriod = cycles >> 5; + } else + if (cycles < TIMER1_RESOLUTION * 64) { + clockSelectBits = 6; + pwmPeriod = cycles >> 6; + } else + if (cycles < TIMER1_RESOLUTION * 128) { + clockSelectBits = 7; + pwmPeriod = cycles >> 7; + } else { + clockSelectBits = 7; + pwmPeriod = TIMER1_RESOLUTION - 1; + } + + uint32_t sc = FTM1_SC; + FTM1_SC = 0; + FTM1_MOD = pwmPeriod; + FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_CPWMS | clockSelectBits | (sc & FTM_SC_TOIE); + } + + //**************************** + // Run Control + //**************************** + void start() __attribute__((always_inline)) { + stop(); + FTM1_CNT = 0; + resume(); + } + void stop() __attribute__((always_inline)) { + FTM1_SC = FTM1_SC & (FTM_SC_TOIE | FTM_SC_CPWMS | FTM_SC_PS(7)); + } + void restart() __attribute__((always_inline)) { + start(); + } + void resume() __attribute__((always_inline)) { + FTM1_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1); + } + + //**************************** + // PWM outputs + //**************************** + void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) { + unsigned long dutyCycle = pwmPeriod; + dutyCycle *= duty; + dutyCycle >>= 10; + if (pin == TIMER1_A_PIN) { + FTM1_C0V = dutyCycle; + } else if (pin == TIMER1_B_PIN) { + FTM1_C1V = dutyCycle; + } + } + void pwm(char pin, unsigned int duty) __attribute__((always_inline)) { + setPwmDuty(pin, duty); + if (pin == TIMER1_A_PIN) { + *portConfigRegister(TIMER1_A_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; + } else if (pin == TIMER1_B_PIN) { + *portConfigRegister(TIMER1_B_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; + } + } + void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) { + if (microseconds > 0) setPeriod(microseconds); + pwm(pin, duty); + } + void disablePwm(char pin) __attribute__((always_inline)) { + if (pin == TIMER1_A_PIN) { + *portConfigRegister(TIMER1_A_PIN) = 0; + } else if (pin == TIMER1_B_PIN) { + *portConfigRegister(TIMER1_B_PIN) = 0; + } + } + + //**************************** + // Interrupt Function + //**************************** + void attachInterrupt(void (*isr)()) __attribute__((always_inline)) { + isrCallback = isr; + FTM1_SC |= FTM_SC_TOIE; + NVIC_ENABLE_IRQ(IRQ_FTM1); + } + void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) { + if(microseconds > 0) setPeriod(microseconds); + attachInterrupt(isr); + } + void detachInterrupt() __attribute__((always_inline)) { + FTM1_SC &= ~FTM_SC_TOIE; + NVIC_DISABLE_IRQ(IRQ_FTM1); + } + static void (*isrCallback)(); + static void isrDefaultUnused(); + + private: + // properties + static unsigned short pwmPeriod; + static unsigned char clockSelectBits; + +#undef F_TIMER + +#endif }; extern TimerOne Timer1; -#endif \ No newline at end of file + +#endif + diff --git a/cnc_ctrl_v1/config/known_16bit_timers.h b/cnc_ctrl_v1/config/known_16bit_timers.h new file mode 100755 index 00000000..bdae3302 --- /dev/null +++ b/cnc_ctrl_v1/config/known_16bit_timers.h @@ -0,0 +1,153 @@ +#ifndef known_16bit_timers_header_ +#define known_16bit_timers_header_ + +// Wiring-S +// +#if defined(__AVR_ATmega644P__) && defined(WIRING) + #define TIMER1_A_PIN 5 + #define TIMER1_B_PIN 4 + #define TIMER1_ICP_PIN 6 + +// Teensy 2.0 +// +#elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY) + #define TIMER1_A_PIN 14 + #define TIMER1_B_PIN 15 + #define TIMER1_C_PIN 4 + #define TIMER1_ICP_PIN 22 + #define TIMER1_CLK_PIN 11 + #define TIMER3_A_PIN 9 + #define TIMER3_ICP_PIN 10 + +// Teensy++ 2.0 +#elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY) + #define TIMER1_A_PIN 25 + #define TIMER1_B_PIN 26 + #define TIMER1_C_PIN 27 + #define TIMER1_ICP_PIN 4 + #define TIMER1_CLK_PIN 6 + #define TIMER3_A_PIN 16 + #define TIMER3_B_PIN 15 + #define TIMER3_C_PIN 14 + #define TIMER3_ICP_PIN 17 + #define TIMER3_CLK_PIN 13 + +// Teensy 3.0 +// +#elif defined(__MK20DX128__) + #define TIMER1_A_PIN 3 + #define TIMER1_B_PIN 4 + #define TIMER1_ICP_PIN 4 + +// Teensy 3.1 / Teensy 3.2 +// +#elif defined(__MK20DX256__) + #define TIMER1_A_PIN 3 + #define TIMER1_B_PIN 4 + #define TIMER1_ICP_PIN 4 + #define TIMER3_A_PIN 32 + #define TIMER3_B_PIN 25 + #define TIMER3_ICP_PIN 32 + +// Teensy 3.5 / Teensy 3.6 +// +#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) + #define TIMER1_A_PIN 3 + #define TIMER1_B_PIN 4 + #define TIMER1_ICP_PIN 4 + #define TIMER3_A_PIN 29 + #define TIMER3_B_PIN 30 + #define TIMER3_ICP_PIN 29 + +// Teensy-LC +// +#elif defined(__MKL26Z64__) + #define TIMER1_A_PIN 16 + #define TIMER1_B_PIN 17 + #define TIMER1_ICP_PIN 17 + #define TIMER3_A_PIN 3 + #define TIMER3_B_PIN 4 + #define TIMER3_ICP_PIN 4 + +// Arduino Mega +// +#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + #define TIMER1_A_PIN 11 + #define TIMER1_B_PIN 12 + #define TIMER1_C_PIN 13 + #define TIMER3_A_PIN 5 + #define TIMER3_B_PIN 2 + #define TIMER3_C_PIN 3 + #define TIMER4_A_PIN 6 + #define TIMER4_B_PIN 7 + #define TIMER4_C_PIN 8 + #define TIMER4_ICP_PIN 49 + #define TIMER5_A_PIN 46 + #define TIMER5_B_PIN 45 + #define TIMER5_C_PIN 44 + #define TIMER3_ICP_PIN 48 + #define TIMER3_CLK_PIN 47 + +// Arduino Leonardo, Yun, etc +// +#elif defined(__AVR_ATmega32U4__) + #define TIMER1_A_PIN 9 + #define TIMER1_B_PIN 10 + #define TIMER1_C_PIN 11 + #define TIMER1_ICP_PIN 4 + #define TIMER1_CLK_PIN 12 + #define TIMER3_A_PIN 5 + #define TIMER3_ICP_PIN 13 + +// Uno, Duemilanove, LilyPad, etc +// +#elif defined (__AVR_ATmega168__) || defined (__AVR_ATmega328P__) + #define TIMER1_A_PIN 9 + #define TIMER1_B_PIN 10 + #define TIMER1_ICP_PIN 8 + #define TIMER1_CLK_PIN 5 + +// Sanguino +// +#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) + #define TIMER1_A_PIN 13 + #define TIMER1_B_PIN 12 + #define TIMER1_ICP_PIN 14 + #define TIMER1_CLK_PIN 1 + +// Wildfire - Wicked Devices +// +#elif defined(__AVR_ATmega1284P__) && defined(WILDFIRE_VERSION) && WILDFIRE_VERSION >= 3 + #define TIMER1_A_PIN 5 // PD5 + #define TIMER1_B_PIN 8 // PD4 + #define TIMER1_ICP_PIN 6 // PD6 + #define TIMER1_CLK_PIN 23 // PB1 + #define TIMER3_A_PIN 12 // PB6 + #define TIMER3_B_PIN 13 // PB7 + #define TIMER3_ICP_PIN 9 // PB5 + #define TIMER3_CLK_PIN 0 // PD0 +#elif defined(__AVR_ATmega1284P__) && defined(WILDFIRE_VERSION) && WILDFIRE_VERSION < 3 + #define TIMER1_A_PIN 5 // PD5 + #define TIMER1_B_PIN 4 // PD4 + #define TIMER1_ICP_PIN 6 // PD6 + #define TIMER1_CLK_PIN 15 // PB1 + #define TIMER3_A_PIN 12 // PB6 + #define TIMER3_B_PIN 13 // PB7 + #define TIMER3_ICP_PIN 11 // PB5 + #define TIMER3_CLK_PIN 0 // PD0 + +// Mighty-1284 - Maniacbug +// +#elif defined(__AVR_ATmega1284P__) + #define TIMER1_A_PIN 12 // PD5 + #define TIMER1_B_PIN 13 // PD4 + #define TIMER1_ICP_PIN 14 // PD6 + #define TIMER1_CLK_PIN 1 // PB1 + #define TIMER3_A_PIN 6 // PB6 + #define TIMER3_B_PIN 7 // PB7 + #define TIMER3_ICP_PIN 5 // PB5 + #define TIMER3_CLK_PIN 8 // PD0 + +#endif + +#endif diff --git a/cnc_ctrl_v1/utility/direct_pin_read.h b/cnc_ctrl_v1/utility/direct_pin_read.h old mode 100644 new mode 100755 index 97b88620..1f36d59c --- a/cnc_ctrl_v1/utility/direct_pin_read.h +++ b/cnc_ctrl_v1/utility/direct_pin_read.h @@ -1,7 +1,7 @@ #ifndef direct_pin_read_h_ #define direct_pin_read_h_ -#if defined(__AVR__) || defined(__MK20DX128__) || defined(__MK20DX256__) +#if defined(__AVR__) || defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) #define IO_REG_TYPE uint8_t #define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin))) From 02c98a88a1c0af2721d1c7dbd864e46fab198688 Mon Sep 17 00:00:00 2001 From: Scott Smith Date: Fri, 8 Dec 2017 12:13:18 -0800 Subject: [PATCH 2/9] Revert "Update TimerOne for Teensy" This reverts commit 20b01b559471f3acdb6d7a32fe156f5d15ece38f. --- cnc_ctrl_v1/TimerOne.cpp | 213 ++++++++-- cnc_ctrl_v1/TimerOne.h | 519 +++--------------------- cnc_ctrl_v1/config/known_16bit_timers.h | 153 ------- cnc_ctrl_v1/utility/direct_pin_read.h | 2 +- 4 files changed, 237 insertions(+), 650 deletions(-) mode change 100755 => 100644 cnc_ctrl_v1/TimerOne.cpp mode change 100755 => 100644 cnc_ctrl_v1/TimerOne.h delete mode 100755 cnc_ctrl_v1/config/known_16bit_timers.h mode change 100755 => 100644 cnc_ctrl_v1/utility/direct_pin_read.h diff --git a/cnc_ctrl_v1/TimerOne.cpp b/cnc_ctrl_v1/TimerOne.cpp old mode 100755 new mode 100644 index 7e838d0a..efede8d3 --- a/cnc_ctrl_v1/TimerOne.cpp +++ b/cnc_ctrl_v1/TimerOne.cpp @@ -3,52 +3,207 @@ * Original code by Jesse Tane for http://labs.ideo.com August 2008 * Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support * Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop - * Modified Oct 2009 by Dan Clemens to work with timer1 of the ATMega1280 or Arduino Mega - * Modified April 2012 by Paul Stoffregen - * Modified again, June 2014 by Paul Stoffregen - * Modified July 2017 by Stoyko Dimitrov - added support for ATTiny85 except for the PWM functionality + * Modified June 2011 by Lex Talionis to add a function to read the timer + * Modified Oct 2011 by Andrew Richards to avoid certain problems: + * - Add (long) assignments and casts to TimerOne::read() to ensure calculations involving tmp, ICR1 and TCNT1 aren't truncated + * - Ensure 16 bit registers accesses are atomic - run with interrupts disabled when accessing + * - Remove global enable of interrupts (sei())- could be running within an interrupt routine) + * - Disable interrupts whilst TCTN1 == 0. Datasheet vague on this, but experiment shows that overflow interrupt + * flag gets set whilst TCNT1 == 0, resulting in a phantom interrupt. Could just set to 1, but gets inaccurate + * at very short durations + * - startBottom() added to start counter at 0 and handle all interrupt enabling. + * - start() amended to enable interrupts + * - restart() amended to point at startBottom() + * Modiied 7:26 PM Sunday, October 09, 2011 by Lex Talionis + * - renamed start() to resume() to reflect it's actual role + * - renamed startBottom() to start(). This breaks some old code that expects start to continue counting where it left off * - * This is free software. You can redistribute it and/or modify it under - * the terms of Creative Commons Attribution 3.0 United States License. - * To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/ - * or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * See Google Code project http://code.google.com/p/arduino-timerone/ for latest */ +#ifndef TIMERONE_cpp +#define TIMERONE_cpp #include "TimerOne.h" TimerOne Timer1; // preinstatiate -unsigned short TimerOne::pwmPeriod = 0; -unsigned char TimerOne::clockSelectBits = 0; -void (*TimerOne::isrCallback)() = TimerOne::isrDefaultUnused; - -// interrupt service routine that wraps a user defined function supplied by attachInterrupt -#if defined (__AVR_ATtiny85__) -ISR(TIMER1_COMPA_vect) +ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt { Timer1.isrCallback(); } -#elif defined(__AVR__) -ISR(TIMER1_OVF_vect) + + +void TimerOne::initialize(long microseconds) { - Timer1.isrCallback(); + TCCR1A = 0; // clear control register A + TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm, stop the timer + setPeriod(microseconds); } -#elif defined(__arm__) && defined(CORE_TEENSY) -void ftm1_isr(void) + +void TimerOne::setPeriod(long microseconds) // AR modified for atomic access { - uint32_t sc = FTM1_SC; - #ifdef KINETISL - if (sc & 0x80) FTM1_SC = sc; - #else - if (sc & 0x80) FTM1_SC = sc & 0x7F; - #endif - Timer1.isrCallback(); + + long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2 + if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal + else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8 + else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64 + else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256 + else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024 + else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum + + oldSREG = SREG; + cli(); // Disable interrupts for 16 bit register access + ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode + SREG = oldSREG; + + TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); + TCCR1B |= clockSelectBits; // reset clock select register, and starts the clock } -#endif +void TimerOne::setPwmDuty(char pin, int duty) +{ + unsigned long dutyCycle = pwmPeriod; + + dutyCycle *= duty; + dutyCycle >>= 10; + + oldSREG = SREG; + cli(); + if(pin == 1 || pin == 9) OCR1A = dutyCycle; + else if(pin == 2 || pin == 10) OCR1B = dutyCycle; + SREG = oldSREG; +} + +void TimerOne::pwm(char pin, int duty, long microseconds) // expects duty cycle to be 10 bit (1024) +{ + if(microseconds > 0) setPeriod(microseconds); + if(pin == 1 || pin == 9) { + DDRB |= _BV(PORTB1); // sets data direction register for pwm output pin + TCCR1A |= _BV(COM1A1); // activates the output pin + } + else if(pin == 2 || pin == 10) { + DDRB |= _BV(PORTB2); + TCCR1A |= _BV(COM1B1); + } + setPwmDuty(pin, duty); + resume(); // Lex - make sure the clock is running. We don't want to restart the count, in case we are starting the second WGM + // and the first one is in the middle of a cycle +} + +void TimerOne::disablePwm(char pin) +{ + if(pin == 1 || pin == 9) TCCR1A &= ~_BV(COM1A1); // clear the bit that enables pwm on PB1 + else if(pin == 2 || pin == 10) TCCR1A &= ~_BV(COM1B1); // clear the bit that enables pwm on PB2 +} + +void TimerOne::attachInterrupt(void (*isr)(), long microseconds) +{ + if(microseconds > 0) setPeriod(microseconds); + isrCallback = isr; // register the user's callback with the real ISR + TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit + // might be running with interrupts disabled (eg inside an ISR), so don't touch the global state +// sei(); + resume(); +} -void TimerOne::isrDefaultUnused() +void TimerOne::detachInterrupt() { + TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit + // timer continues to count without calling the isr } + +void TimerOne::resume() // AR suggested +{ + TCCR1B |= clockSelectBits; +} + +void TimerOne::restart() // Depricated - Public interface to start at zero - Lex 10/9/2011 +{ + start(); +} + +void TimerOne::start() // AR addition, renamed by Lex to reflect it's actual role +{ + unsigned int tcnt1; + + TIMSK1 &= ~_BV(TOIE1); // AR added + GTCCR |= _BV(PSRSYNC); // AR added - reset prescaler (NB: shared with all 16 bit timers); + + oldSREG = SREG; // AR - save status register + cli(); // AR - Disable interrupts + TCNT1 = 0; + SREG = oldSREG; // AR - Restore status register + resume(); + do { // Nothing -- wait until timer moved on from zero - otherwise get a phantom interrupt + oldSREG = SREG; + cli(); + tcnt1 = TCNT1; + SREG = oldSREG; + } while (tcnt1==0); + +// TIFR1 = 0xff; // AR - Clear interrupt flags +// TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit +} + +void TimerOne::stop() +{ + TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits +} + +unsigned long TimerOne::read() //returns the value of the timer in microseconds +{ //rember! phase and freq correct mode counts up to then down again + unsigned long tmp; // AR amended to hold more than 65536 (could be nearly double this) + unsigned int tcnt1; // AR added + + oldSREG= SREG; + cli(); + tmp=TCNT1; + SREG = oldSREG; + + char scale=0; + switch (clockSelectBits) + { + case 1:// no prescalse + scale=0; + break; + case 2:// x8 prescale + scale=3; + break; + case 3:// x64 + scale=6; + break; + case 4:// x256 + scale=8; + break; + case 5:// x1024 + scale=10; + break; + } + + do { // Nothing -- max delay here is ~1023 cycles. AR modified + oldSREG = SREG; + cli(); + tcnt1 = TCNT1; + SREG = oldSREG; + } while (tcnt1==tmp); //if the timer has not ticked yet + + //if we are counting down add the top value to how far we have counted down + tmp = ( (tcnt1>tmp) ? (tmp) : (long)(ICR1-tcnt1)+(long)ICR1 ); // AR amended to add casts and reuse previous TCNT1 + return ((tmp*1000L)/(F_CPU /1000L))<. + * + * See Google Code project http://code.google.com/p/arduino-timerone/ for latest */ +#ifndef TIMERONE_h +#define TIMERONE_h -#ifndef TimerOne_h_ -#define TimerOne_h_ - -#if defined(ARDUINO) && ARDUINO >= 100 -#include "Arduino.h" -#else -#include "WProgram.h" -#endif - -#include "config/known_16bit_timers.h" -#if defined (__AVR_ATtiny85__) -#define TIMER1_RESOLUTION 256UL // Timer1 is 8 bit -#elif defined(__AVR__) -#define TIMER1_RESOLUTION 65536UL // Timer1 is 16 bit -#else -#define TIMER1_RESOLUTION 65536UL // assume 16 bits for non-AVR chips -#endif - -// Placing nearly all the code in this .h file allows the functions to be -// inlined by the compiler. In the very common case with constant values -// the compiler will perform all calculations and simply write constants -// to the hardware registers (for example, setPeriod). +#include +#include +#define RESOLUTION 65536 // Timer1 is 16 bit class TimerOne { - -#if defined (__AVR_ATtiny85__) - public: - //**************************** - // Configuration - //**************************** - void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) { - TCCR1 = _BV(CTC1); //clear timer1 when it matches the value in OCR1C - TIMSK |= _BV(OCIE1A); //enable interrupt when OCR1A matches the timer value - setPeriod(microseconds); - } - void setPeriod(unsigned long microseconds) __attribute__((always_inline)) { - const unsigned long cycles = microseconds * ratio; - if (cycles < TIMER1_RESOLUTION) { - clockSelectBits = _BV(CS10); - pwmPeriod = cycles; - } else - if (cycles < TIMER1_RESOLUTION * 2UL) { - clockSelectBits = _BV(CS11); - pwmPeriod = cycles / 2; - } else - if (cycles < TIMER1_RESOLUTION * 4UL) { - clockSelectBits = _BV(CS11) | _BV(CS10); - pwmPeriod = cycles / 4; - } else - if (cycles < TIMER1_RESOLUTION * 8UL) { - clockSelectBits = _BV(CS12); - pwmPeriod = cycles / 8; - } else - if (cycles < TIMER1_RESOLUTION * 16UL) { - clockSelectBits = _BV(CS12) | _BV(CS10); - pwmPeriod = cycles / 16; - } else - if (cycles < TIMER1_RESOLUTION * 32UL) { - clockSelectBits = _BV(CS12) | _BV(CS11); - pwmPeriod = cycles / 32; - } else - if (cycles < TIMER1_RESOLUTION * 64UL) { - clockSelectBits = _BV(CS12) | _BV(CS11) | _BV(CS10); - pwmPeriod = cycles / 64UL; - } else - if (cycles < TIMER1_RESOLUTION * 128UL) { - clockSelectBits = _BV(CS13); - pwmPeriod = cycles / 128; - } else - if (cycles < TIMER1_RESOLUTION * 256UL) { - clockSelectBits = _BV(CS13) | _BV(CS10); - pwmPeriod = cycles / 256; - } else - if (cycles < TIMER1_RESOLUTION * 512UL) { - clockSelectBits = _BV(CS13) | _BV(CS11); - pwmPeriod = cycles / 512; - } else - if (cycles < TIMER1_RESOLUTION * 1024UL) { - clockSelectBits = _BV(CS13) | _BV(CS11) | _BV(CS10); - pwmPeriod = cycles / 1024; - } else - if (cycles < TIMER1_RESOLUTION * 2048UL) { - clockSelectBits = _BV(CS13) | _BV(CS12); - pwmPeriod = cycles / 2048; - } else - if (cycles < TIMER1_RESOLUTION * 4096UL) { - clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS10); - pwmPeriod = cycles / 4096; - } else - if (cycles < TIMER1_RESOLUTION * 8192UL) { - clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11); - pwmPeriod = cycles / 8192; - } else - if (cycles < TIMER1_RESOLUTION * 16384UL) { - clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11) | _BV(CS10); - pwmPeriod = cycles / 16384; - } else { - clockSelectBits = _BV(CS13) | _BV(CS12) | _BV(CS11) | _BV(CS10); - pwmPeriod = TIMER1_RESOLUTION - 1; - } - OCR1A = pwmPeriod; - OCR1C = pwmPeriod; - TCCR1 = _BV(CTC1) | clockSelectBits; - } - - //**************************** - // Run Control - //**************************** - void start() __attribute__((always_inline)) { - TCCR1 = 0; - TCNT1 = 0; - resume(); - } - void stop() __attribute__((always_inline)) { - TCCR1 = _BV(CTC1); - } - void restart() __attribute__((always_inline)) { - start(); - } - void resume() __attribute__((always_inline)) { - TCCR1 = _BV(CTC1) | clockSelectBits; - } - - //**************************** - // PWM outputs - //**************************** - //Not implemented yet for ATTiny85 - //TO DO - - //**************************** - // Interrupt Function - //**************************** - void attachInterrupt(void (*isr)()) __attribute__((always_inline)) { - isrCallback = isr; - TIMSK |= _BV(OCIE1A); - } - void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) { - if(microseconds > 0) setPeriod(microseconds); - attachInterrupt(isr); - } - void detachInterrupt() __attribute__((always_inline)) { - //TIMSK = 0; // Timer 0 and Timer 1 both use TIMSK register so setting it to 0 will override settings for Timer1 as well - TIMSK &= ~_BV(OCIE1A); - } - static void (*isrCallback)(); - static void isrDefaultUnused(); - - private: - static unsigned short pwmPeriod; - static unsigned char clockSelectBits; - static const byte ratio = (F_CPU)/ ( 1000000 ); - -#elif defined(__AVR__) public: - //**************************** - // Configuration - //**************************** - void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) { - TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer - TCCR1A = 0; // clear control register A - setPeriod(microseconds); - } - void setPeriod(unsigned long microseconds) __attribute__((always_inline)) { - const unsigned long cycles = (F_CPU / 2000000) * microseconds; - if (cycles < TIMER1_RESOLUTION) { - clockSelectBits = _BV(CS10); - pwmPeriod = cycles; - } else - if (cycles < TIMER1_RESOLUTION * 8) { - clockSelectBits = _BV(CS11); - pwmPeriod = cycles / 8; - } else - if (cycles < TIMER1_RESOLUTION * 64) { - clockSelectBits = _BV(CS11) | _BV(CS10); - pwmPeriod = cycles / 64; - } else - if (cycles < TIMER1_RESOLUTION * 256) { - clockSelectBits = _BV(CS12); - pwmPeriod = cycles / 256; - } else - if (cycles < TIMER1_RESOLUTION * 1024) { - clockSelectBits = _BV(CS12) | _BV(CS10); - pwmPeriod = cycles / 1024; - } else { - clockSelectBits = _BV(CS12) | _BV(CS10); - pwmPeriod = TIMER1_RESOLUTION - 1; - } - ICR1 = pwmPeriod; - TCCR1B = _BV(WGM13) | clockSelectBits; - } - - //**************************** - // Run Control - //**************************** - void start() __attribute__((always_inline)) { - TCCR1B = 0; - TCNT1 = 0; // TODO: does this cause an undesired interrupt? - resume(); - } - void stop() __attribute__((always_inline)) { - TCCR1B = _BV(WGM13); - } - void restart() __attribute__((always_inline)) { - start(); - } - void resume() __attribute__((always_inline)) { - TCCR1B = _BV(WGM13) | clockSelectBits; - } - - //**************************** - // PWM outputs - //**************************** - void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) { - unsigned long dutyCycle = pwmPeriod; - dutyCycle *= duty; - dutyCycle >>= 10; - if (pin == TIMER1_A_PIN) OCR1A = dutyCycle; - #ifdef TIMER1_B_PIN - else if (pin == TIMER1_B_PIN) OCR1B = dutyCycle; - #endif - #ifdef TIMER1_C_PIN - else if (pin == TIMER1_C_PIN) OCR1C = dutyCycle; - #endif - } - void pwm(char pin, unsigned int duty) __attribute__((always_inline)) { - if (pin == TIMER1_A_PIN) { pinMode(TIMER1_A_PIN, OUTPUT); TCCR1A |= _BV(COM1A1); } - #ifdef TIMER1_B_PIN - else if (pin == TIMER1_B_PIN) { pinMode(TIMER1_B_PIN, OUTPUT); TCCR1A |= _BV(COM1B1); } - #endif - #ifdef TIMER1_C_PIN - else if (pin == TIMER1_C_PIN) { pinMode(TIMER1_C_PIN, OUTPUT); TCCR1A |= _BV(COM1C1); } - #endif - setPwmDuty(pin, duty); - TCCR1B = _BV(WGM13) | clockSelectBits; - } - void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) { - if (microseconds > 0) setPeriod(microseconds); - pwm(pin, duty); - } - void disablePwm(char pin) __attribute__((always_inline)) { - if (pin == TIMER1_A_PIN) TCCR1A &= ~_BV(COM1A1); - #ifdef TIMER1_B_PIN - else if (pin == TIMER1_B_PIN) TCCR1A &= ~_BV(COM1B1); - #endif - #ifdef TIMER1_C_PIN - else if (pin == TIMER1_C_PIN) TCCR1A &= ~_BV(COM1C1); - #endif - } - - //**************************** - // Interrupt Function - //**************************** - void attachInterrupt(void (*isr)()) __attribute__((always_inline)) { - isrCallback = isr; - TIMSK1 = _BV(TOIE1); - } - void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) { - if(microseconds > 0) setPeriod(microseconds); - attachInterrupt(isr); - } - void detachInterrupt() __attribute__((always_inline)) { - TIMSK1 = 0; - } - static void (*isrCallback)(); - static void isrDefaultUnused(); - - private: + // properties - static unsigned short pwmPeriod; - static unsigned char clockSelectBits; - - - - - - -#elif defined(__arm__) && defined(CORE_TEENSY) - -#if defined(KINETISK) -#define F_TIMER F_BUS -#elif defined(KINETISL) -#define F_TIMER (F_PLL/2) -#endif - - public: - //**************************** - // Configuration - //**************************** - void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) { - setPeriod(microseconds); - } - void setPeriod(unsigned long microseconds) __attribute__((always_inline)) { - const unsigned long cycles = (F_TIMER / 2000000) * microseconds; - // A much faster if-else - // This is like a binary serch tree and no more than 3 conditions are evaluated. - // I haven't checked if this becomes significantly longer ASM than the simple ladder. - // It looks very similar to the ladder tho: same # of if's and else's - - /* - // This code does not work properly in all cases :( - // https://github.com/PaulStoffregen/TimerOne/issues/17 - if (cycles < TIMER1_RESOLUTION * 16) { - if (cycles < TIMER1_RESOLUTION * 4) { - if (cycles < TIMER1_RESOLUTION) { - clockSelectBits = 0; - pwmPeriod = cycles; - }else{ - clockSelectBits = 1; - pwmPeriod = cycles >> 1; - } - }else{ - if (cycles < TIMER1_RESOLUTION * 8) { - clockSelectBits = 3; - pwmPeriod = cycles >> 3; - }else{ - clockSelectBits = 4; - pwmPeriod = cycles >> 4; - } - } - }else{ - if (cycles > TIMER1_RESOLUTION * 64) { - if (cycles > TIMER1_RESOLUTION * 128) { - clockSelectBits = 7; - pwmPeriod = TIMER1_RESOLUTION - 1; - }else{ - clockSelectBits = 7; - pwmPeriod = cycles >> 7; - } - } - else{ - if (cycles > TIMER1_RESOLUTION * 32) { - clockSelectBits = 6; - pwmPeriod = cycles >> 6; - }else{ - clockSelectBits = 5; - pwmPeriod = cycles >> 5; - } - } - } - */ - if (cycles < TIMER1_RESOLUTION) { - clockSelectBits = 0; - pwmPeriod = cycles; - } else - if (cycles < TIMER1_RESOLUTION * 2) { - clockSelectBits = 1; - pwmPeriod = cycles >> 1; - } else - if (cycles < TIMER1_RESOLUTION * 4) { - clockSelectBits = 2; - pwmPeriod = cycles >> 2; - } else - if (cycles < TIMER1_RESOLUTION * 8) { - clockSelectBits = 3; - pwmPeriod = cycles >> 3; - } else - if (cycles < TIMER1_RESOLUTION * 16) { - clockSelectBits = 4; - pwmPeriod = cycles >> 4; - } else - if (cycles < TIMER1_RESOLUTION * 32) { - clockSelectBits = 5; - pwmPeriod = cycles >> 5; - } else - if (cycles < TIMER1_RESOLUTION * 64) { - clockSelectBits = 6; - pwmPeriod = cycles >> 6; - } else - if (cycles < TIMER1_RESOLUTION * 128) { - clockSelectBits = 7; - pwmPeriod = cycles >> 7; - } else { - clockSelectBits = 7; - pwmPeriod = TIMER1_RESOLUTION - 1; - } - - uint32_t sc = FTM1_SC; - FTM1_SC = 0; - FTM1_MOD = pwmPeriod; - FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_CPWMS | clockSelectBits | (sc & FTM_SC_TOIE); - } - - //**************************** - // Run Control - //**************************** - void start() __attribute__((always_inline)) { - stop(); - FTM1_CNT = 0; - resume(); - } - void stop() __attribute__((always_inline)) { - FTM1_SC = FTM1_SC & (FTM_SC_TOIE | FTM_SC_CPWMS | FTM_SC_PS(7)); - } - void restart() __attribute__((always_inline)) { - start(); - } - void resume() __attribute__((always_inline)) { - FTM1_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1); - } - - //**************************** - // PWM outputs - //**************************** - void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) { - unsigned long dutyCycle = pwmPeriod; - dutyCycle *= duty; - dutyCycle >>= 10; - if (pin == TIMER1_A_PIN) { - FTM1_C0V = dutyCycle; - } else if (pin == TIMER1_B_PIN) { - FTM1_C1V = dutyCycle; - } - } - void pwm(char pin, unsigned int duty) __attribute__((always_inline)) { - setPwmDuty(pin, duty); - if (pin == TIMER1_A_PIN) { - *portConfigRegister(TIMER1_A_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; - } else if (pin == TIMER1_B_PIN) { - *portConfigRegister(TIMER1_B_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE; - } - } - void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) { - if (microseconds > 0) setPeriod(microseconds); - pwm(pin, duty); - } - void disablePwm(char pin) __attribute__((always_inline)) { - if (pin == TIMER1_A_PIN) { - *portConfigRegister(TIMER1_A_PIN) = 0; - } else if (pin == TIMER1_B_PIN) { - *portConfigRegister(TIMER1_B_PIN) = 0; - } - } - - //**************************** - // Interrupt Function - //**************************** - void attachInterrupt(void (*isr)()) __attribute__((always_inline)) { - isrCallback = isr; - FTM1_SC |= FTM_SC_TOIE; - NVIC_ENABLE_IRQ(IRQ_FTM1); - } - void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) { - if(microseconds > 0) setPeriod(microseconds); - attachInterrupt(isr); - } - void detachInterrupt() __attribute__((always_inline)) { - FTM1_SC &= ~FTM_SC_TOIE; - NVIC_DISABLE_IRQ(IRQ_FTM1); - } - static void (*isrCallback)(); - static void isrDefaultUnused(); - - private: - // properties - static unsigned short pwmPeriod; - static unsigned char clockSelectBits; - -#undef F_TIMER - -#endif + unsigned int pwmPeriod; + unsigned char clockSelectBits; + char oldSREG; // To hold Status Register while ints disabled + + // methods + void initialize(long microseconds=1000000); + void start(); + void stop(); + void restart(); + void resume(); + unsigned long read(); + void pwm(char pin, int duty, long microseconds=-1); + void disablePwm(char pin); + void attachInterrupt(void (*isr)(), long microseconds=-1); + void detachInterrupt(); + void setPeriod(long microseconds); + void setPwmDuty(char pin, int duty); + void (*isrCallback)(); }; extern TimerOne Timer1; - -#endif - +#endif \ No newline at end of file diff --git a/cnc_ctrl_v1/config/known_16bit_timers.h b/cnc_ctrl_v1/config/known_16bit_timers.h deleted file mode 100755 index bdae3302..00000000 --- a/cnc_ctrl_v1/config/known_16bit_timers.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef known_16bit_timers_header_ -#define known_16bit_timers_header_ - -// Wiring-S -// -#if defined(__AVR_ATmega644P__) && defined(WIRING) - #define TIMER1_A_PIN 5 - #define TIMER1_B_PIN 4 - #define TIMER1_ICP_PIN 6 - -// Teensy 2.0 -// -#elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY) - #define TIMER1_A_PIN 14 - #define TIMER1_B_PIN 15 - #define TIMER1_C_PIN 4 - #define TIMER1_ICP_PIN 22 - #define TIMER1_CLK_PIN 11 - #define TIMER3_A_PIN 9 - #define TIMER3_ICP_PIN 10 - -// Teensy++ 2.0 -#elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY) - #define TIMER1_A_PIN 25 - #define TIMER1_B_PIN 26 - #define TIMER1_C_PIN 27 - #define TIMER1_ICP_PIN 4 - #define TIMER1_CLK_PIN 6 - #define TIMER3_A_PIN 16 - #define TIMER3_B_PIN 15 - #define TIMER3_C_PIN 14 - #define TIMER3_ICP_PIN 17 - #define TIMER3_CLK_PIN 13 - -// Teensy 3.0 -// -#elif defined(__MK20DX128__) - #define TIMER1_A_PIN 3 - #define TIMER1_B_PIN 4 - #define TIMER1_ICP_PIN 4 - -// Teensy 3.1 / Teensy 3.2 -// -#elif defined(__MK20DX256__) - #define TIMER1_A_PIN 3 - #define TIMER1_B_PIN 4 - #define TIMER1_ICP_PIN 4 - #define TIMER3_A_PIN 32 - #define TIMER3_B_PIN 25 - #define TIMER3_ICP_PIN 32 - -// Teensy 3.5 / Teensy 3.6 -// -#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) - #define TIMER1_A_PIN 3 - #define TIMER1_B_PIN 4 - #define TIMER1_ICP_PIN 4 - #define TIMER3_A_PIN 29 - #define TIMER3_B_PIN 30 - #define TIMER3_ICP_PIN 29 - -// Teensy-LC -// -#elif defined(__MKL26Z64__) - #define TIMER1_A_PIN 16 - #define TIMER1_B_PIN 17 - #define TIMER1_ICP_PIN 17 - #define TIMER3_A_PIN 3 - #define TIMER3_B_PIN 4 - #define TIMER3_ICP_PIN 4 - -// Arduino Mega -// -#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - #define TIMER1_A_PIN 11 - #define TIMER1_B_PIN 12 - #define TIMER1_C_PIN 13 - #define TIMER3_A_PIN 5 - #define TIMER3_B_PIN 2 - #define TIMER3_C_PIN 3 - #define TIMER4_A_PIN 6 - #define TIMER4_B_PIN 7 - #define TIMER4_C_PIN 8 - #define TIMER4_ICP_PIN 49 - #define TIMER5_A_PIN 46 - #define TIMER5_B_PIN 45 - #define TIMER5_C_PIN 44 - #define TIMER3_ICP_PIN 48 - #define TIMER3_CLK_PIN 47 - -// Arduino Leonardo, Yun, etc -// -#elif defined(__AVR_ATmega32U4__) - #define TIMER1_A_PIN 9 - #define TIMER1_B_PIN 10 - #define TIMER1_C_PIN 11 - #define TIMER1_ICP_PIN 4 - #define TIMER1_CLK_PIN 12 - #define TIMER3_A_PIN 5 - #define TIMER3_ICP_PIN 13 - -// Uno, Duemilanove, LilyPad, etc -// -#elif defined (__AVR_ATmega168__) || defined (__AVR_ATmega328P__) - #define TIMER1_A_PIN 9 - #define TIMER1_B_PIN 10 - #define TIMER1_ICP_PIN 8 - #define TIMER1_CLK_PIN 5 - -// Sanguino -// -#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) - #define TIMER1_A_PIN 13 - #define TIMER1_B_PIN 12 - #define TIMER1_ICP_PIN 14 - #define TIMER1_CLK_PIN 1 - -// Wildfire - Wicked Devices -// -#elif defined(__AVR_ATmega1284P__) && defined(WILDFIRE_VERSION) && WILDFIRE_VERSION >= 3 - #define TIMER1_A_PIN 5 // PD5 - #define TIMER1_B_PIN 8 // PD4 - #define TIMER1_ICP_PIN 6 // PD6 - #define TIMER1_CLK_PIN 23 // PB1 - #define TIMER3_A_PIN 12 // PB6 - #define TIMER3_B_PIN 13 // PB7 - #define TIMER3_ICP_PIN 9 // PB5 - #define TIMER3_CLK_PIN 0 // PD0 -#elif defined(__AVR_ATmega1284P__) && defined(WILDFIRE_VERSION) && WILDFIRE_VERSION < 3 - #define TIMER1_A_PIN 5 // PD5 - #define TIMER1_B_PIN 4 // PD4 - #define TIMER1_ICP_PIN 6 // PD6 - #define TIMER1_CLK_PIN 15 // PB1 - #define TIMER3_A_PIN 12 // PB6 - #define TIMER3_B_PIN 13 // PB7 - #define TIMER3_ICP_PIN 11 // PB5 - #define TIMER3_CLK_PIN 0 // PD0 - -// Mighty-1284 - Maniacbug -// -#elif defined(__AVR_ATmega1284P__) - #define TIMER1_A_PIN 12 // PD5 - #define TIMER1_B_PIN 13 // PD4 - #define TIMER1_ICP_PIN 14 // PD6 - #define TIMER1_CLK_PIN 1 // PB1 - #define TIMER3_A_PIN 6 // PB6 - #define TIMER3_B_PIN 7 // PB7 - #define TIMER3_ICP_PIN 5 // PB5 - #define TIMER3_CLK_PIN 8 // PD0 - -#endif - -#endif diff --git a/cnc_ctrl_v1/utility/direct_pin_read.h b/cnc_ctrl_v1/utility/direct_pin_read.h old mode 100755 new mode 100644 index 1f36d59c..97b88620 --- a/cnc_ctrl_v1/utility/direct_pin_read.h +++ b/cnc_ctrl_v1/utility/direct_pin_read.h @@ -1,7 +1,7 @@ #ifndef direct_pin_read_h_ #define direct_pin_read_h_ -#if defined(__AVR__) || defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) +#if defined(__AVR__) || defined(__MK20DX128__) || defined(__MK20DX256__) #define IO_REG_TYPE uint8_t #define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin))) From 912ffd57e3e1f8fefaf80c613d468194179367c2 Mon Sep 17 00:00:00 2001 From: Scott Smith Date: Tue, 20 Feb 2018 00:14:13 -0800 Subject: [PATCH 3/9] disable simavr --- platformio.ini | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platformio.ini b/platformio.ini index f87ad0b1..b9641e81 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,10 +16,10 @@ platform = atmelavr board = megaatmega2560 framework = arduino -[env:simavr] -platform = atmelavr -board = megaatmega2560 -framework = arduino -extra_scripts = simavr_env_for_platformio.py -build_unflags = -Os -build_flags = -g -O0 +; [env:simavr] +; platform = atmelavr +; board = megaatmega2560 +; framework = arduino +; extra_scripts = simavr_env_for_platformio.py +; build_unflags = -Os +; build_flags = -g -O0 From f4298a47a5f34637d28a49af9c80fba817d9aa7c Mon Sep 17 00:00:00 2001 From: Scott Smith Date: Fri, 23 Feb 2018 09:21:27 -0800 Subject: [PATCH 4/9] Revert "disable simavr" This reverts commit 912ffd57e3e1f8fefaf80c613d468194179367c2. --- platformio.ini | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platformio.ini b/platformio.ini index b9641e81..f87ad0b1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,10 +16,10 @@ platform = atmelavr board = megaatmega2560 framework = arduino -; [env:simavr] -; platform = atmelavr -; board = megaatmega2560 -; framework = arduino -; extra_scripts = simavr_env_for_platformio.py -; build_unflags = -Os -; build_flags = -g -O0 +[env:simavr] +platform = atmelavr +board = megaatmega2560 +framework = arduino +extra_scripts = simavr_env_for_platformio.py +build_unflags = -Os +build_flags = -g -O0 From 6e61770a9078b4dbeb15a7cb83be5597fef28dae Mon Sep 17 00:00:00 2001 From: Scott Smith Date: Wed, 28 Mar 2018 15:58:47 -0700 Subject: [PATCH 5/9] Move AUX pin definitions and make them defined at runtime Using a function "configAuxLow(int AUX1, int AUX2, int AUX3, int AUX4, int AUX5, int AUX6)" to associate the AUX pin values with variables prevents the compiler from warning about unused variables. Is there a different way? Leaving the debug print statements in until testers have evaluated the PR. The 'dummyPin' uses an AUX pin that differs between board versions. The v1.0 board should show '1', the v1.1 and v1.2 boards should show '60'. Added comments to Probe.cpp and Spindle.cpp to tell where the active pins are assigned. --- cnc_ctrl_v1/Config.h | 28 +++---- cnc_ctrl_v1/Probe.cpp | 4 +- cnc_ctrl_v1/Spindle.cpp | 18 +++-- cnc_ctrl_v1/System.cpp | 144 +++++++++++++++++++++++++----------- cnc_ctrl_v1/System.h | 8 +- cnc_ctrl_v1/cnc_ctrl_v1.ino | 8 ++ 6 files changed, 136 insertions(+), 74 deletions(-) diff --git a/cnc_ctrl_v1/Config.h b/cnc_ctrl_v1/Config.h index 4dd06b37..501139d2 100644 --- a/cnc_ctrl_v1/Config.h +++ b/cnc_ctrl_v1/Config.h @@ -9,10 +9,10 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the Maslow Control Software. If not, see . - + Copyright 2014-2017 Bar Smith*/ -// This file contains precompile configuration settings that apply to the +// This file contains precompile configuration settings that apply to the // whole system #ifndef config_h @@ -20,7 +20,7 @@ // Debugging Options #define verboseDebug 0 // set to 0 for no debug messages, 1 for single-line messages, 2 to also output ring buffer contents -#define misloopDebug 0 // set to 1 for a warning every time the movement loop fails +#define misloopDebug 0 // set to 1 for a warning every time the movement loop fails // to complete before being interrupted, helpful for loop // LOOPINTERVAL tuning #define KINEMATICSDBG 0 // set to 1 for additional kinematics debug messaging @@ -35,30 +35,22 @@ #define LOOPINTERVAL 10000 // What is the frequency of the PID loop in microseconds -// Define extra pins -#define AUX1 17 -#define AUX2 16 -#define AUX3 15 -#define AUX4 14 -#define SpindlePowerControlPin AUX1 // output for controlling spindle power -#define ProbePin AUX4 // use this input for zeroing zAxis with G38.2 gcode - // Serial variables #define INCBUFFERLENGTH 128 // The number of bytes(characters) allocated to the // incoming buffer. -#define EXPGCODELINE 60 // Maximum expected Gcode line length in characters - // including line ending character(s). Assumes - // client will not send more than this. Ground +#define EXPGCODELINE 60 // Maximum expected Gcode line length in characters + // including line ending character(s). Assumes + // client will not send more than this. Ground // Control is currently set to 60. NIST spec allows // 256. This value must be <= INCBUFFERLENGTH #define MAXBUFFERLINES 4 // The maximum number of lines allowed in the buffer -#define POSITIONTIMEOUT 200 // The minimum number of milliseconds between - // position reports sent to Ground Control. This - // cannot be larger than the connection timout in +#define POSITIONTIMEOUT 200 // The minimum number of milliseconds between + // position reports sent to Ground Control. This + // cannot be larger than the connection timout in // Ground Control which is 2000, a smaller number // takes more processing time for sending data // a larger number make position updates in GC less // smooth. This is only a minimum, and the actual - // timeout could be significantly larger. + // timeout could be significantly larger. #endif diff --git a/cnc_ctrl_v1/Probe.cpp b/cnc_ctrl_v1/Probe.cpp index f9340dc3..619fc09a 100644 --- a/cnc_ctrl_v1/Probe.cpp +++ b/cnc_ctrl_v1/Probe.cpp @@ -19,6 +19,8 @@ Copyright 2014-2017 Bar Smith*/ #include "Maslow.h" +// the variable probePin is assigned in configAuxLow() in System.cpp + bool checkForProbeTouch(const int& probePin) { /* Check to see if ProbePin has gone LOW @@ -28,4 +30,4 @@ bool checkForProbeTouch(const int& probePin) { return 1; } return 0; -} \ No newline at end of file +} diff --git a/cnc_ctrl_v1/Spindle.cpp b/cnc_ctrl_v1/Spindle.cpp index 9dec8125..3384d848 100644 --- a/cnc_ctrl_v1/Spindle.cpp +++ b/cnc_ctrl_v1/Spindle.cpp @@ -9,20 +9,22 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the Maslow Control Software. If not, see . - + Copyright 2014-2017 Bar Smith*/ // This contains all of the Spindle commands #include "Maslow.h" +// the variable SpindlePowerControlPin is assigned in configAuxLow() in System.cpp + // Globals for Spindle control, both poorly named -Servo myservo; // create servo object to control a servo +Servo myservo; // create servo object to control a servo void setSpindlePower(bool powerState) { /* * Turn spindle on or off depending on powerState - */ + */ boolean useServo = !sysSettings.spindleAutomate; boolean activeHigh = true; int delayAfterChange = 1000; // milliseconds @@ -30,14 +32,14 @@ void setSpindlePower(bool powerState) { int servoOn = 180; // degrees int servoOff = 0; // degrees int servoDelay = 2000; // milliseconds - + // Now for the main code - #if defined (verboseDebug) && verboseDebug > 1 + #if defined (verboseDebug) && verboseDebug > 1 Serial.print(F("Spindle control uses pin ")); Serial.print(SpindlePowerControlPin); #endif if (useServo) { // use a servo to control a standard wall switch - #if defined (verboseDebug) && verboseDebug > 1 + #if defined (verboseDebug) && verboseDebug > 1 Serial.print(F(" with servo (idle=")); Serial.print(servoIdle); Serial.print(F(", on=")); @@ -66,7 +68,7 @@ void setSpindlePower(bool powerState) { myservo.detach(); // stop servo control } else { // use a digital I/O pin to control a relay - #if defined (verboseDebug) && verboseDebug > 1 + #if defined (verboseDebug) && verboseDebug > 1 Serial.print(F(" as digital output, active ")); if (activeHigh) Serial.println(F("high")); else Serial.println(F("low")); @@ -84,4 +86,4 @@ void setSpindlePower(bool powerState) { } } maslowDelay(delayAfterChange); -} \ No newline at end of file +} diff --git a/cnc_ctrl_v1/System.cpp b/cnc_ctrl_v1/System.cpp index 5f16cf90..e8531489 100644 --- a/cnc_ctrl_v1/System.cpp +++ b/cnc_ctrl_v1/System.cpp @@ -19,44 +19,49 @@ Copyright 2014-2017 Bar Smith*/ #include "Maslow.h" +// extern values using AUX pins defined in configAuxLow() and configAuxHigh() +int SpindlePowerControlPin; // output for controlling spindle power +int ProbePin; // use this input for zeroing zAxis with G38.2 gcode +int dummyPin; + void calibrateChainLengths(String gcodeLine){ /* The calibrateChainLengths function lets the machine know that the chains are set to a given length where each chain is ORIGINCHAINLEN in length */ - + if (extractGcodeValue(gcodeLine, 'L', 0)){ //measure out the left chain Serial.println(F("Measuring out left chain")); singleAxisMove(&leftAxis, sysSettings.originalChainLength, (sysSettings.maxFeed * .9)); - + Serial.print(leftAxis.read()); Serial.println(F("mm")); - + leftAxis.detach(); } else if(extractGcodeValue(gcodeLine, 'R', 0)){ //measure out the right chain Serial.println(F("Measuring out right chain")); singleAxisMove(&rightAxis, sysSettings.originalChainLength, (sysSettings.maxFeed * .9)); - + Serial.print(rightAxis.read()); Serial.println(F("mm")); - + rightAxis.detach(); } - + } void setupAxes(){ /* - + Detect the version of the Arduino shield connected, and use the appropriate pins - + This function runs before the serial port is open so the version is not printed here - + */ - + // These shouldn't be CAPS, they are not precompile defines int ENCODER1A; int ENCODER1B; @@ -64,21 +69,28 @@ void setupAxes(){ int ENCODER2B; int ENCODER3A; int ENCODER3B; - + int IN1; int IN2; int IN3; int IN4; int IN5; int IN6; - + int ENA; int ENB; int ENC; - + + int AUX1; + int AUX2; + int AUX3; + int AUX4; + int AUX5; + int AUX6; + //read the pins which indicate the PCB version int pcbVersion = getPCBVersion(); - + if(pcbVersion == 0){ //Beta PCB v1.0 Detected //MP1 - Right Motor @@ -87,20 +99,28 @@ void setupAxes(){ IN1 = 9; // OUTPUT IN2 = 8; // OUTPUT ENA = 6; // PWM - + //MP2 - Z-axis ENCODER2A = 2; // INPUT ENCODER2B = 3; // INPUT IN3 = 11; // OUTPUT IN4 = 10; // OUTPUT ENB = 7; // PWM - + //MP3 - Left Motor ENCODER3A = 21; // INPUT ENCODER3B = 20; // INPUT IN5 = 12; // OUTPUT IN6 = 13; // OUTPUT ENC = 5; // PWM + + //AUX pins + AUX1 = 17; + AUX2 = 16; + AUX3 = 15; + AUX4 = 14; + AUX5 = 0; // warning! this is the serial TX line on the Mega2560 + AUX6 = 1; // warning! this is the serial RX line on the Mega2560 } else if(pcbVersion == 1){ //PCB v1.1 Detected @@ -110,38 +130,46 @@ void setupAxes(){ IN1 = 6; // OUTPUT IN2 = 4; // OUTPUT ENA = 5; // PWM - + //MP2 - Z-axis ENCODER2A = 19; // INPUT ENCODER2B = 18; // INPUT IN3 = 9; // OUTPUT IN4 = 7; // OUTPUT ENB = 8; // PWM - + //MP3 - Left Motor ENCODER3A = 2; // INPUT ENCODER3B = 3; // INPUT IN5 = 10; // OUTPUT IN6 = 11; // OUTPUT ENC = 12; // PWM + + //AUX pins + AUX1 = 17; + AUX2 = 16; + AUX3 = 15; + AUX4 = 14; + AUX5 = A7; + AUX6 = A6; } else if(pcbVersion == 2){ //PCB v1.2 Detected - + //MP1 - Right Motor ENCODER1A = 20; // INPUT ENCODER1B = 21; // INPUT IN1 = 4; // OUTPUT IN2 = 6; // OUTPUT ENA = 5; // PWM - + //MP2 - Z-axis ENCODER2A = 19; // INPUT ENCODER2B = 18; // INPUT IN3 = 7; // OUTPUT IN4 = 9; // OUTPUT ENB = 8; // PWM - + //MP3 - Left Motor ENCODER3A = 2; // INPUT ENCODER3B = 3; // INPUT @@ -149,7 +177,13 @@ void setupAxes(){ IN6 = 12; // OUTPUT ENC = 10; // PWM - + //AUX pins + AUX1 = 17; + AUX2 = 16; + AUX3 = 15; + AUX4 = 14; + AUX5 = A7; + AUX6 = A6; } if(sysSettings.chainOverSprocket == 1){ @@ -160,13 +194,33 @@ void setupAxes(){ leftAxis.setup (ENC, IN5, IN6, ENCODER3A, ENCODER3B, 'L', LOOPINTERVAL); rightAxis.setup(ENA, IN2, IN1, ENCODER1B, ENCODER1A, 'R', LOOPINTERVAL); } - + zAxis.setup (ENB, IN3, IN4, ENCODER2B, ENCODER2A, 'Z', LOOPINTERVAL); leftAxis.setPIDValues(&sysSettings.KpPos, &sysSettings.KiPos, &sysSettings.KdPos, &sysSettings.propWeightPos, &sysSettings.KpV, &sysSettings.KiV, &sysSettings.KdV, &sysSettings.propWeightV); rightAxis.setPIDValues(&sysSettings.KpPos, &sysSettings.KiPos, &sysSettings.KdPos, &sysSettings.propWeightPos, &sysSettings.KpV, &sysSettings.KiV, &sysSettings.KdV, &sysSettings.propWeightV); zAxis.setPIDValues(&sysSettings.zKpPos, &sysSettings.zKiPos, &sysSettings.zKdPos, &sysSettings.zPropWeightPos, &sysSettings.zKpV, &sysSettings.zKiV, &sysSettings.zKdV, &sysSettings.zPropWeightV); + + // implement the AUXx values that are 'used'. This accomplishes setting their values at runtime. + // Using a separate function is a compiler work-around to avoid + // "warning: variable ‘xxxxx’ set but not used [-Wunused-but-set-variable]" + // for AUX pins defined but not connected + configAuxLow(AUX1, AUX2, AUX3, AUX4, AUX5, AUX6); } +// Assign AUX pins to extern variables used by functions like Spindle and Probe +void configAuxLow(int AUX1, int AUX2, int AUX3, int AUX4, int AUX5, int AUX6) { + SpindlePowerControlPin = AUX1; // output for controlling spindle power + ProbePin = AUX4; // use this input for zeroing zAxis with G38.2 gcode + dummyPin = AUX6; + Serial.print(F("SpindlePowerControlPin = ")); + Serial.println(SpindlePowerControlPin); // output for controlling spindle power + Serial.print(F("ProbePin = ")); + Serial.println(ProbePin); + Serial.print(F("dummyPin = ")); + Serial.println(dummyPin); +} + + int getPCBVersion(){ return (8*digitalRead(53) + 4*digitalRead(52) + 2*digitalRead(23) + 1*digitalRead(22)) - 1; } @@ -209,7 +263,7 @@ void setPWMPrescalers(int prescalerChoice) { // Code: TCCR2B = (TCCR2B & 0xF8) | value ; // —————————————————————————————- // Timers 3, 4 ( Pin 2, 3, 5), (Pin 6, 7, 8) -// +// // Value Divisor Frequency // 0x01 1 31.374 KHz // 0x02 8 3.921 Khz @@ -259,24 +313,24 @@ void setPWMPrescalers() { // Need to check if all returns from this subsequently look to sys.stop void pause(){ /* - + The pause command pauses the machine in place without flushing the lines stored in the machine's buffer. - - When paused the machine enters a while() loop and doesn't exit until the '~' cycle resume command + + When paused the machine enters a while() loop and doesn't exit until the '~' cycle resume command is issued from Ground Control. - + */ - + bit_true(sys.pause, PAUSE_FLAG_USER_PAUSE); Serial.println(F("Maslow Paused")); - + while(bit_istrue(sys.pause, PAUSE_FLAG_USER_PAUSE)) { - + // Run realtime commands execSystemRealtime(); if (sys.stop){return;} - } + } } @@ -291,13 +345,13 @@ void maslowDelay(unsigned long waitTimeMs) { * Provides a time delay while holding the machine position, reading serial commands, * and periodically sending the machine position to Ground Control. This prevents * Ground Control from thinking that the connection is lost. - * + * * This is similar to the pause() command above, but provides a time delay rather than * waiting for the user (through Ground Control) to tell the machine to continue. */ - + unsigned long startTime = millis(); - + while ((millis() - startTime) < waitTimeMs){ execSystemRealtime(); if (sys.stop){return;} @@ -326,29 +380,29 @@ void systemSaveAxesPosition(){ } } -// This should be the ultimate fallback, it would be best if we didn't even need +// This should be the ultimate fallback, it would be best if we didn't even need // something like this at all // TODO delete this function, we are not even using it anymore void _watchDog(){ /* If: - No incoming serial in 5 seconds + No incoming serial in 5 seconds Motors are detached Nothing in Serial buffer Watchdog has not run in 5 seconds Then: Send an ok message - + This fixes the issue where the machine is ready, but Ground Control doesn't know the machine is ready and the system locks up. */ static unsigned long lastRan = millis(); - + if ( millis() - sys.lastSerialRcvd > 5000 && - (millis() - lastRan) > 5000 && + (millis() - lastRan) > 5000 && !leftAxis.attached() and !rightAxis.attached() and !zAxis.attached() && incSerialBuffer.length() == 0 ){ - #if defined (verboseDebug) && verboseDebug > 0 + #if defined (verboseDebug) && verboseDebug > 0 Serial.println(F("_watchDog requesting new code")); #endif reportStatusMessage(STATUS_OK); @@ -357,7 +411,7 @@ void _watchDog(){ } void systemReset(){ - /* + /* Stops everything and resets the arduino */ leftAxis.detach(); @@ -448,14 +502,14 @@ byte systemExecuteCmdstring(String& cmdString){ // if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { // sys.state = STATE_HOMING; // Set system state variable // // Only perform homing if Grbl is idle or lost. - // + // // // TODO: Likely not required. // if (system_check_safety_door_ajar()) { // Check safety door switch before homing. // bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR); // protocol_execute_realtime(); // Enter safety door mode. // } - // - // + // + // // mc_homing_cycle(); // if (!sys.abort) { // Execute startup scripts after successful homing. // sys.state = STATE_IDLE; // Set to IDLE when complete. diff --git a/cnc_ctrl_v1/System.h b/cnc_ctrl_v1/System.h index 670db5c5..a2ef8d86 100644 --- a/cnc_ctrl_v1/System.h +++ b/cnc_ctrl_v1/System.h @@ -39,7 +39,7 @@ Copyright 2014-2017 Bar Smith*/ #define STATE_CYCLE bit(3) // Cycle is running or motions are being executed. #define STATE_HOLD bit(4) // Active feed hold #define STATE_SAFETY_DOOR bit(5) // Safety door is ajar. Feed holds and de-energizes system. -#define STATE_MOTION_CANCEL bit(6) // Motion cancel by feed hold and return to idle. +#define STATE_MOTION_CANCEL bit(6) // Motion cancel by feed hold and return to idle. // Define old settings flag details #define NEED_ENCODER_STEPS bit(0) @@ -56,7 +56,7 @@ typedef struct { float xPosition; // Cartessian position of XY axes float yPosition; // Cached because calculating position is intensive float steps[3]; // Encoder position of axes - bool useRelativeUnits; // + bool useRelativeUnits; // unsigned long lastSerialRcvd; // The millis of the last rcvd serial command, used by watchdo int lastGCommand; //Stores the value of the last command run eg: G01 -> 1 int lastTool; //Stores the value of the last tool number eg: T4 -> 4 @@ -74,6 +74,9 @@ extern Axis zAxis; extern RingBuffer incSerialBuffer; extern Kinematics kinematics; extern byte systemRtExecAlarm; +extern int SpindlePowerControlPin; +extern int ProbePin; +extern int dummyPin; void calibrateChainLengths(String); void setupAxes(); @@ -86,6 +89,7 @@ void systemSaveAxesPosition(); void systemReset(); byte systemExecuteCmdstring(String&); void setPWMPrescalers(int prescalerChoice); +void configAuxLow(int A1, int A2, int A3, int A4, int A5, int A6); #endif diff --git a/cnc_ctrl_v1/cnc_ctrl_v1.ino b/cnc_ctrl_v1/cnc_ctrl_v1.ino index cf5d85e0..032cbea9 100644 --- a/cnc_ctrl_v1/cnc_ctrl_v1.ino +++ b/cnc_ctrl_v1/cnc_ctrl_v1.ino @@ -75,6 +75,14 @@ void setup(){ Serial.println(F("Grbl v1.00")); // Why GRBL? Apparently because some programs are silly and look for this as an initialization command Serial.println(F("ready")); reportStatusMessage(STATUS_OK); + + Serial.print(F("SpindlePowerControlPin = ")); + Serial.println(SpindlePowerControlPin); // output for controlling spindle power + Serial.print(F("ProbePin = ")); + Serial.println(ProbePin); + Serial.print(F("dummyPin = ")); + Serial.println(dummyPin); + } void runsOnATimer(){ From fd53aebf1355320a3054a71a276dd6a66c95833b Mon Sep 17 00:00:00 2001 From: Scott Smith Date: Fri, 30 Mar 2018 21:26:58 -0700 Subject: [PATCH 6/9] Clean up testing code --- cnc_ctrl_v1/System.cpp | 8 -------- cnc_ctrl_v1/cnc_ctrl_v1.ino | 23 ----------------------- 2 files changed, 31 deletions(-) diff --git a/cnc_ctrl_v1/System.cpp b/cnc_ctrl_v1/System.cpp index e8531489..134e0d59 100644 --- a/cnc_ctrl_v1/System.cpp +++ b/cnc_ctrl_v1/System.cpp @@ -22,7 +22,6 @@ Copyright 2014-2017 Bar Smith*/ // extern values using AUX pins defined in configAuxLow() and configAuxHigh() int SpindlePowerControlPin; // output for controlling spindle power int ProbePin; // use this input for zeroing zAxis with G38.2 gcode -int dummyPin; void calibrateChainLengths(String gcodeLine){ /* @@ -211,13 +210,6 @@ void setupAxes(){ void configAuxLow(int AUX1, int AUX2, int AUX3, int AUX4, int AUX5, int AUX6) { SpindlePowerControlPin = AUX1; // output for controlling spindle power ProbePin = AUX4; // use this input for zeroing zAxis with G38.2 gcode - dummyPin = AUX6; - Serial.print(F("SpindlePowerControlPin = ")); - Serial.println(SpindlePowerControlPin); // output for controlling spindle power - Serial.print(F("ProbePin = ")); - Serial.println(ProbePin); - Serial.print(F("dummyPin = ")); - Serial.println(dummyPin); } diff --git a/cnc_ctrl_v1/cnc_ctrl_v1.ino b/cnc_ctrl_v1/cnc_ctrl_v1.ino index 032cbea9..44db3b8a 100644 --- a/cnc_ctrl_v1/cnc_ctrl_v1.ino +++ b/cnc_ctrl_v1/cnc_ctrl_v1.ino @@ -9,27 +9,16 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the Maslow Control Software. If not, see . - Copyright 2014-2017 Bar Smith*/ - - /* To the projects contributers: - * - * it is highly recommended to activate warning output of the arduino gcc compiler. * Compiler warnings are a great help to keep the codebase clean and can give clues - * to potentally wrong code. Also, if a codebase produces too many warnings it gets - * more likely that possibly important warnings could be overlooked. * * Since the Arduino IDE suppresses any compiler output by default we have to activate it. * - * Therefore Arduino IDE users need to activate compiler output in the * preferences dialog. Additionally Arduino IDE needs to tell the compiler to generate - * warning messages. This is done in the Arduino IDE's preferences.txt file - you can - * get there via the Preferences Dialog - there is a link to the file at the bottom. * Edit the line "compiler.warning_level=none" to "compiler.warning_level=all" * and restart the IDE. */ - #include "Maslow.h" // Define system global state structure @@ -39,7 +28,6 @@ system_t sys; settings_t sysSettings; // Global realtime executor bitflag variable for setting various alarms. -byte systemRtExecAlarm; // Define axes, it might be tighter to define these within the sys struct Axis leftAxis; @@ -71,18 +59,10 @@ void setup(){ Timer1.initialize(LOOPINTERVAL); Timer1.attachInterrupt(runsOnATimer); #endif - Serial.println(F("Grbl v1.00")); // Why GRBL? Apparently because some programs are silly and look for this as an initialization command Serial.println(F("ready")); reportStatusMessage(STATUS_OK); - Serial.print(F("SpindlePowerControlPin = ")); - Serial.println(SpindlePowerControlPin); // output for controlling spindle power - Serial.print(F("ProbePin = ")); - Serial.println(ProbePin); - Serial.print(F("dummyPin = ")); - Serial.println(dummyPin); - } void runsOnATimer(){ @@ -101,12 +81,9 @@ void loop(){ // This section is called on startup and whenever a stop command is issued initGCode(); if (sys.stop){ // only called on sys.stop to prevent stopping - initMotion(); // on USB disconnect. Might consider removing - setSpindlePower(false); // this restriction for safety if we are } // comfortable that USB disconnects are // not a common occurence anymore kinematics.init(); - // Let's go! sys.stop = false; // We should consider an abort option which // is not reset automatically such as a software From 88ae27d890923530e12f5fd3d1596bb46dd80266 Mon Sep 17 00:00:00 2001 From: Scott Smith Date: Fri, 30 Mar 2018 21:49:55 -0700 Subject: [PATCH 7/9] corrections of partial commit errors --- cnc_ctrl_v1/System.h | 1 - cnc_ctrl_v1/cnc_ctrl_v1.ino | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/cnc_ctrl_v1/System.h b/cnc_ctrl_v1/System.h index a2ef8d86..3c7f2967 100644 --- a/cnc_ctrl_v1/System.h +++ b/cnc_ctrl_v1/System.h @@ -76,7 +76,6 @@ extern Kinematics kinematics; extern byte systemRtExecAlarm; extern int SpindlePowerControlPin; extern int ProbePin; -extern int dummyPin; void calibrateChainLengths(String); void setupAxes(); diff --git a/cnc_ctrl_v1/cnc_ctrl_v1.ino b/cnc_ctrl_v1/cnc_ctrl_v1.ino index 44db3b8a..d59fcf2c 100644 --- a/cnc_ctrl_v1/cnc_ctrl_v1.ino +++ b/cnc_ctrl_v1/cnc_ctrl_v1.ino @@ -9,16 +9,26 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the Maslow Control Software. If not, see . + Copyright 2014-2017 Bar Smith*/ + + /* To the projects contributers: + * it is highly recommended to activate warning output of the arduino gcc compiler. * Compiler warnings are a great help to keep the codebase clean and can give clues + * to potentally wrong code. Also, if a codebase produces too many warnings it gets + * more likely that possibly important warnings could be overlooked. * * Since the Arduino IDE suppresses any compiler output by default we have to activate it. * + * Therefore Arduino IDE users need to activate compiler output in the * preferences dialog. Additionally Arduino IDE needs to tell the compiler to generate + * warning messages. This is done in the Arduino IDE's preferences.txt file - you can + * get there via the Preferences Dialog - there is a link to the file at the bottom. * Edit the line "compiler.warning_level=none" to "compiler.warning_level=all" * and restart the IDE. */ + #include "Maslow.h" // Define system global state structure @@ -28,6 +38,7 @@ system_t sys; settings_t sysSettings; // Global realtime executor bitflag variable for setting various alarms. +byte systemRtExecAlarm; // Define axes, it might be tighter to define these within the sys struct Axis leftAxis; @@ -59,6 +70,7 @@ void setup(){ Timer1.initialize(LOOPINTERVAL); Timer1.attachInterrupt(runsOnATimer); #endif + Serial.println(F("Grbl v1.00")); // Why GRBL? Apparently because some programs are silly and look for this as an initialization command Serial.println(F("ready")); reportStatusMessage(STATUS_OK); @@ -81,9 +93,12 @@ void loop(){ // This section is called on startup and whenever a stop command is issued initGCode(); if (sys.stop){ // only called on sys.stop to prevent stopping + initMotion(); // on USB disconnect. Might consider removing + setSpindlePower(false); // this restriction for safety if we are } // comfortable that USB disconnects are // not a common occurence anymore kinematics.init(); + // Let's go! sys.stop = false; // We should consider an abort option which // is not reset automatically such as a software From b8736d150e14d4079369496816d8849c7a60b157 Mon Sep 17 00:00:00 2001 From: Scott Smith Date: Fri, 30 Mar 2018 21:57:08 -0700 Subject: [PATCH 8/9] replace lost comment line --- cnc_ctrl_v1/cnc_ctrl_v1.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/cnc_ctrl_v1/cnc_ctrl_v1.ino b/cnc_ctrl_v1/cnc_ctrl_v1.ino index d59fcf2c..cb3fbeed 100644 --- a/cnc_ctrl_v1/cnc_ctrl_v1.ino +++ b/cnc_ctrl_v1/cnc_ctrl_v1.ino @@ -15,6 +15,7 @@ /* To the projects contributers: * it is highly recommended to activate warning output of the arduino gcc compiler. + * * Compiler warnings are a great help to keep the codebase clean and can give clues * to potentally wrong code. Also, if a codebase produces too many warnings it gets * more likely that possibly important warnings could be overlooked. From d176a32d0a09896910f507e7a615d591b4931aeb Mon Sep 17 00:00:00 2001 From: Scott Smith Date: Fri, 30 Mar 2018 21:59:41 -0700 Subject: [PATCH 9/9] one more try at that comment line... --- cnc_ctrl_v1/cnc_ctrl_v1.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cnc_ctrl_v1/cnc_ctrl_v1.ino b/cnc_ctrl_v1/cnc_ctrl_v1.ino index cb3fbeed..03804b93 100644 --- a/cnc_ctrl_v1/cnc_ctrl_v1.ino +++ b/cnc_ctrl_v1/cnc_ctrl_v1.ino @@ -14,8 +14,8 @@ /* To the projects contributers: - * it is highly recommended to activate warning output of the arduino gcc compiler. * + * it is highly recommended to activate warning output of the arduino gcc compiler. * Compiler warnings are a great help to keep the codebase clean and can give clues * to potentally wrong code. Also, if a codebase produces too many warnings it gets * more likely that possibly important warnings could be overlooked.