Add and apply interrupt helper macros

This commit is contained in:
Scott Lahteine 2017-04-20 13:20:08 -05:00 committed by Scott Lahteine
parent 6131c62499
commit ee46ce1743
3 changed files with 112 additions and 90 deletions

View file

@ -11524,15 +11524,13 @@ void prepare_move_to_destination() {
#ifdef TCCR0A #ifdef TCCR0A
case TIMER0A: case TIMER0A:
case TIMER0B: case TIMER0B:
// TCCR0B &= ~(_BV(CS00) | _BV(CS01) | _BV(CS02)); //SET_CS(0, val);
// TCCR0B |= val;
break; break;
#endif #endif
#ifdef TCCR1A #ifdef TCCR1A
case TIMER1A: case TIMER1A:
case TIMER1B: case TIMER1B:
// TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); //SET_CS(1, val);
// TCCR1B |= val;
break; break;
#endif #endif
#ifdef TCCR2 #ifdef TCCR2
@ -11545,32 +11543,28 @@ void prepare_move_to_destination() {
#ifdef TCCR2A #ifdef TCCR2A
case TIMER2A: case TIMER2A:
case TIMER2B: case TIMER2B:
TCCR2B &= ~(_BV(CS20) | _BV(CS21) | _BV(CS22)); SET_CS(2, val);
TCCR2B |= val;
break; break;
#endif #endif
#ifdef TCCR3A #ifdef TCCR3A
case TIMER3A: case TIMER3A:
case TIMER3B: case TIMER3B:
case TIMER3C: case TIMER3C:
TCCR3B &= ~(_BV(CS30) | _BV(CS31) | _BV(CS32)); SET_CS(3, val);
TCCR3B |= val;
break; break;
#endif #endif
#ifdef TCCR4A #ifdef TCCR4A
case TIMER4A: case TIMER4A:
case TIMER4B: case TIMER4B:
case TIMER4C: case TIMER4C:
TCCR4B &= ~(_BV(CS40) | _BV(CS41) | _BV(CS42)); SET_CS(4, val);
TCCR4B |= val;
break; break;
#endif #endif
#ifdef TCCR5A #ifdef TCCR5A
case TIMER5A: case TIMER5A:
case TIMER5B: case TIMER5B:
case TIMER5C: case TIMER5C:
TCCR5B &= ~(_BV(CS50) | _BV(CS51) | _BV(CS52)); SET_CS(5, val);
TCCR5B |= val;
break; break;
#endif #endif
} }

View file

@ -21,43 +21,39 @@
*/ */
/** /**
This code contributed by Triffid_Hunter and modified by Kliment * Contributed by Triffid_Hunter, modified by Kliment, extended by the Marlin team
why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html * Why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
*/ */
#ifndef _FASTIO_ARDUINO_H #ifndef _FASTIO_ARDUINO_H
#define _FASTIO_ARDUINO_H #define _FASTIO_ARDUINO_H
#include <avr/io.h> #include <avr/io.h>
/** #ifndef _BV
utility functions #define _BV(PIN) (1 << PIN)
*/
#ifndef MASK
#define MASK(PIN) (1 << PIN)
#endif #endif
/** /**
magic I/O routines * Magic I/O routines
now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0); *
*/ * Now you can simply SET_OUTPUT(PIN); WRITE(PIN, HIGH); WRITE(PIN, LOW);
*/
/// Read a pin #define _READ(IO) ((bool)(DIO ## IO ## _RPORT & _BV(DIO ## IO ## _PIN)))
#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN)))
/// write to a pin
// On some boards pins > 0x100 are used. These are not converted to atomic actions. An critical section is needed.
#define _WRITE_NC(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0) // On some boards pins > 0x100 are used. These are not converted to atomic actions. A critical section is needed.
#define _WRITE_NC(IO, v) do { if (v) {DIO ## IO ## _WPORT |= _BV(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~_BV(DIO ## IO ## _PIN); }; } while (0)
#define _WRITE_C(IO, v) do { if (v) { \ #define _WRITE_C(IO, v) do { if (v) { \
CRITICAL_SECTION_START; \ CRITICAL_SECTION_START; \
{DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } \ {DIO ## IO ## _WPORT |= _BV(DIO ## IO ## _PIN); } \
CRITICAL_SECTION_END; \ CRITICAL_SECTION_END; \
} \ } \
else { \ else { \
CRITICAL_SECTION_START; \ CRITICAL_SECTION_START; \
{DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); } \ {DIO ## IO ## _WPORT &= ~_BV(DIO ## IO ## _PIN); } \
CRITICAL_SECTION_END; \ CRITICAL_SECTION_END; \
} \ } \
} \ } \
@ -65,55 +61,95 @@
#define _WRITE(IO, v) do { if (&(DIO ## IO ## _RPORT) >= (uint8_t *)0x100) {_WRITE_C(IO, v); } else {_WRITE_NC(IO, v); }; } while (0) #define _WRITE(IO, v) do { if (&(DIO ## IO ## _RPORT) >= (uint8_t *)0x100) {_WRITE_C(IO, v); } else {_WRITE_NC(IO, v); }; } while (0)
/// toggle a pin #define _TOGGLE(IO) do {DIO ## IO ## _RPORT ^= _BV(DIO ## IO ## _PIN); } while (0)
#define _TOGGLE(IO) do {DIO ## IO ## _RPORT ^= MASK(DIO ## IO ## _PIN); } while (0)
/// set pin as input #define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~_BV(DIO ## IO ## _PIN); } while (0)
#define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0) #define _SET_OUTPUT(IO) do {DIO ## IO ## _DDR |= _BV(DIO ## IO ## _PIN); } while (0)
/// set pin as output
#define _SET_OUTPUT(IO) do {DIO ## IO ## _DDR |= MASK(DIO ## IO ## _PIN); } while (0)
/// check if pin is an input #define _GET_INPUT(IO) ((DIO ## IO ## _DDR & _BV(DIO ## IO ## _PIN)) == 0)
#define _GET_INPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) == 0) #define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & _BV(DIO ## IO ## _PIN)) != 0)
/// check if pin is an output
#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0)
/// check if pin is an timer
#define _GET_TIMER(IO) (DIO ## IO ## _PWM) #define _GET_TIMER(IO) (DIO ## IO ## _PWM)
// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
/// Read a pin wrapper
#define READ(IO) _READ(IO) #define READ(IO) _READ(IO)
/// Write to a pin wrapper #define WRITE(IO,V) _WRITE(IO,V)
#define WRITE(IO, v) _WRITE(IO, v)
/// toggle a pin wrapper
#define TOGGLE(IO) _TOGGLE(IO) #define TOGGLE(IO) _TOGGLE(IO)
/// set pin as input wrapper
#define SET_INPUT(IO) _SET_INPUT(IO) #define SET_INPUT(IO) _SET_INPUT(IO)
/// set pin as input with pullup wrapper
#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _WRITE(IO, HIGH); }while(0) #define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _WRITE(IO, HIGH); }while(0)
/// set pin as output wrapper
#define SET_OUTPUT(IO) _SET_OUTPUT(IO) #define SET_OUTPUT(IO) _SET_OUTPUT(IO)
/// check if pin is an input wrapper
#define GET_INPUT(IO) _GET_INPUT(IO) #define GET_INPUT(IO) _GET_INPUT(IO)
/// check if pin is an output wrapper
#define GET_OUTPUT(IO) _GET_OUTPUT(IO) #define GET_OUTPUT(IO) _GET_OUTPUT(IO)
/// check if pin is an timer wrapper
#define GET_TIMER(IO) _GET_TIMER(IO) #define GET_TIMER(IO) _GET_TIMER(IO)
// Shorthand #define OUT_WRITE(IO, v) do{ SET_OUTPUT(IO); WRITE(IO, v); }while(0)
#define OUT_WRITE(IO, v) { SET_OUTPUT(IO); WRITE(IO, v); }
/** /**
ports and functions * Interrupt Control
*/
added as necessary or if I feel like it- not a comprehensive list! // Waveform Generation Modes
*/ typedef enum {
WGM_NORMAL, // 0
WGM_PWM_PC_8, // 1
WGM_PWM_PC_9, // 2
WGM_PWM_PC_10, // 3
WGM_CTC_OCRnA, // 4 COM OCnx
WGM_FAST_PWM_8, // 5
WGM_FAST_PWM_9, // 6
WGM_FAST_PWM_10, // 7
WGM_PWM_PC_FC_ICRn, // 8
WGM_PWM_PC_FC_OCRnA, // 9 COM OCnA
WGM_PWM_PC_ICRn, // 10
WGM_PWM_PC_OCRnA, // 11 COM OCnA
WGM_CTC_ICRn, // 12 COM OCnx
WGM_reserved, // 13
WGM_FAST_PWM_ICRn, // 14 COM OCnA
WGM_FAST_PWM_OCRnA // 15 COM OCnA
} WaveGenMode;
// Compare Modes
typedef enum {
COM_NORMAL, // 0
COM_TOGGLE, // 1 Non-PWM: OCnx ... Both PWM (WGM 9,11,14,15): OCnA only ... else NORMAL
COM_CLEAR_SET, // 2 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down
COM_SET_CLEAR // 3 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down
} CompareMode;
// Clock Sources
typedef enum {
CS_NONE, // 0
CS_PRESCALER_1, // 1
CS_PRESCALER_8, // 2
CS_PRESCALER_64, // 3
CS_PRESCALER_256, // 4
CS_PRESCALER_1024, // 5
CS_EXT_FALLING, // 6
CS_EXT_RISING // 7
} ClockSource;
#define SET_WGM(T,V) do{ \
TCCR##T##A = (TCCR##T##A & ~(0x3 << WGM##T##0)) | (( int(V) & 0x3) << WGM##T##0); \
TCCR##T##B = (TCCR##T##B & ~(0x3 << WGM##T##2)) | (((int(V) >> 2) & 0x3) << WGM##T##2); \
}while(0)
#define SET_CS(T,V) do{ \
TCCR##T##B = (TCCR##T##B & ~(0x7 << CS10)) | ((int(V) & 0x7) << CS10); \
}while(0)
#define SET_COM(T,Q,V) do{ \
TCCR##T##Q = (TCCR##T##Q & !(0x3 << COM1##Q##0) | (int(V) & 0x3) << COM1##Q##0); \
}while(0)
#define SET_COMA(T,V) SET_COM(T,A,V)
#define SET_COMB(T,V) SET_COM(T,B,V)
#define SET_COMS(T,V1,V2) do{ SET_COMA(T,V1); SET_COMB(T,V2); }while(0)
#define SET_ICNC(T,V) (TCCR##T##B = (TCCR##T##B & ~_BV(7) | ((V) & 1) << 7))
#define SET_ICES(T,V) (TCCR##T##B = (TCCR##T##B & ~_BV(6) | ((V) & 1) << 6))
/**
* Ports and Functions
*/
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
// UART // UART
@ -446,7 +482,7 @@
#define PD7_WPORT PORTD #define PD7_WPORT PORTD
#define PD7_DDR DDRD #define PD7_DDR DDRD
#define PD7_PWM NULL #define PD7_PWM NULL
#endif /* _AVR_ATmega{168,328,328P}__ */ #endif // __AVR_ATmega(168|328|328P)__
#if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) #if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__)
// UART // UART
@ -949,7 +985,7 @@
#define PD7_WPORT PORTD #define PD7_WPORT PORTD
#define PD7_DDR DDRD #define PD7_DDR DDRD
#define PD7_PWM OCR2A #define PD7_PWM OCR2A
#endif /* _AVR_ATmega{644,644P,644PA}__ */ #endif // __AVR_ATmega(644|644P|644PA)__
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
// UART // UART
@ -2031,8 +2067,7 @@
#define PL7_WPORT PORTL #define PL7_WPORT PORTL
#define PL7_DDR DDRL #define PL7_DDR DDRL
#define PL7_PWM NULL #define PL7_PWM NULL
#endif // __AVR_ATmega(1280|2560)__
#endif
#if defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) #if defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__)
@ -2040,7 +2075,7 @@
#define DEBUG_LED DIO31 /* led D5 red */ #define DEBUG_LED DIO31 /* led D5 red */
/** /**
pins * pins
*/ */
//#define AT90USBxx_TEENSYPP_ASSIGNMENTS // Use Teensy++ 2.0 assignments //#define AT90USBxx_TEENSYPP_ASSIGNMENTS // Use Teensy++ 2.0 assignments
@ -3335,8 +3370,7 @@
#define PF7_DDR DDRF #define PF7_DDR DDRF
#endif // AT90USBxx_TEENSYPP_ASSIGNMENTS Teensyduino assignments #endif // AT90USBxx_TEENSYPP_ASSIGNMENTS Teensyduino assignments
#endif // __AVR_AT90usbxxx__ #endif // __AVR_AT90USB(1287|1286|646|647)__
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
// UART // UART
@ -4027,12 +4061,10 @@
#define PG5_WPORT PORTG #define PG5_WPORT PORTG
#define PG5_DDR DDRG #define PG5_DDR DDRG
#define PG5_PWM &OCR0B #define PG5_PWM &OCR0B
#endif // __AVR_ATmega(1281|2561)__
#endif
#ifndef DIO0_PIN #ifndef DIO0_PIN
#error "pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please submit a pull request" #error "pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please submit a pull request"
#endif #endif
#endif /* _FASTIO_ARDUINO_H */ #endif // _FASTIO_ARDUINO_H

View file

@ -1081,21 +1081,17 @@ void Stepper::init() {
#endif #endif
// waveform generation = 0100 = CTC // waveform generation = 0100 = CTC
CBI(TCCR1B, WGM13); SET_WGM(1, WGM_CTC_OCRnA);
SBI(TCCR1B, WGM12);
CBI(TCCR1A, WGM11);
CBI(TCCR1A, WGM10);
// output mode = 00 (disconnected) // output mode = 00 (disconnected)
TCCR1A &= ~(3 << COM1A0); SET_COMS(1, COM_NORMAL, COM_NORMAL);
TCCR1A &= ~(3 << COM1B0);
// Set the timer pre-scaler // Set the timer pre-scaler
// Generally we use a divider of 8, resulting in a 2MHz timer // Generally we use a divider of 8, resulting in a 2MHz timer
// frequency on a 16MHz MCU. If you are going to change this, be // frequency on a 16MHz MCU. If you are going to change this, be
// sure to regenerate speed_lookuptable.h with // sure to regenerate speed_lookuptable.h with
// create_speed_lookuptable.py // create_speed_lookuptable.py
TCCR1B = (TCCR1B & ~(0x07 << CS10)) | (2 << CS10); SET_CS(1, CS_PRESCALER_8); // CS 2 = 1/8 prescaler
// Init Stepper ISR to 122 Hz for quick starting // Init Stepper ISR to 122 Hz for quick starting
OCR1A = 0x4000; OCR1A = 0x4000;