Merge Marlin 1.1.8
This commit is contained in:
131
Marlin/fastio.h
131
Marlin/fastio.h
@@ -21,23 +21,23 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fast I/O Routines for AVR
|
||||
* Fast I/O Routines
|
||||
* Use direct port manipulation to save scads of processor time.
|
||||
* Contributed by Triffid_Hunter and modified by Kliment, thinkyhead, Bob-the-Kuhn, et.al.
|
||||
* Contributed by Triffid_Hunter. Modified by Kliment and the Marlin team.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef _FASTIO_ARDUINO_H_
|
||||
#define _FASTIO_ARDUINO_H_
|
||||
#ifndef _FASTIO_ARDUINO_H
|
||||
#define _FASTIO_ARDUINO_H
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "macros.h"
|
||||
|
||||
#define AVR_AT90USB1286_FAMILY (defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1286P__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB646P__) || defined(__AVR_AT90USB647__))
|
||||
#define AVR_ATmega1284_FAMILY (defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__))
|
||||
#define AVR_ATmega2560_FAMILY (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
|
||||
#define AVR_ATmega2561_FAMILY (defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__))
|
||||
#define AVR_ATmega328_FAMILY (defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__))
|
||||
#define AVR_ATmega328_FAMILY (defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328p__))
|
||||
|
||||
|
||||
/**
|
||||
* Include Ports and Functions
|
||||
@@ -53,10 +53,12 @@
|
||||
#elif AVR_ATmega2561_FAMILY
|
||||
#include "fastio_1281.h"
|
||||
#else
|
||||
#error "No FastIO definition for the selected AVR Board."
|
||||
#error "Pins for this chip not defined in Arduino.h! If you have a working pins definition, please contribute!"
|
||||
#endif
|
||||
|
||||
#include "macros.h"
|
||||
#ifndef _BV
|
||||
#define _BV(PIN) (1UL << PIN)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Magic I/O routines
|
||||
@@ -66,50 +68,56 @@
|
||||
* Why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
|
||||
*/
|
||||
|
||||
#define _READ(IO) TEST(DIO ## IO ## _RPORT, DIO ## IO ## _PIN)
|
||||
#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & _BV(DIO ## IO ## _PIN)))
|
||||
|
||||
#define _WRITE_NC(IO,V) do{ \
|
||||
if (V) SBI(DIO ## IO ## _WPORT, DIO ## IO ## _PIN); \
|
||||
else CBI(DIO ## IO ## _WPORT, 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_C(IO,V) do{ \
|
||||
uint8_t port_bits = DIO ## IO ## _WPORT; /* Get a mask from the current port bits */ \
|
||||
if (V) port_bits = ~port_bits; /* For setting bits, invert the mask */ \
|
||||
DIO ## IO ## _RPORT = port_bits & _BV(DIO ## IO ## _PIN); /* Atomically toggle the output port bits */ \
|
||||
}while(0)
|
||||
#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(IO,V) do{ if (&(DIO ## IO ## _RPORT) < (uint8_t*)0x100) _WRITE_NC(IO,V); else _WRITE_C(IO,V); }while(0)
|
||||
#define _WRITE_C(IO, v) do { if (v) { \
|
||||
CRITICAL_SECTION_START; \
|
||||
{DIO ## IO ## _WPORT |= _BV(DIO ## IO ## _PIN); } \
|
||||
CRITICAL_SECTION_END; \
|
||||
} \
|
||||
else { \
|
||||
CRITICAL_SECTION_START; \
|
||||
{DIO ## IO ## _WPORT &= ~_BV(DIO ## IO ## _PIN); } \
|
||||
CRITICAL_SECTION_END; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define _TOGGLE(IO) (DIO ## IO ## _RPORT = _BV(DIO ## IO ## _PIN))
|
||||
#define _WRITE(IO, v) do { if (&(DIO ## IO ## _RPORT) >= (uint8_t *)0x100) {_WRITE_C(IO, v); } else {_WRITE_NC(IO, v); }; } while (0)
|
||||
|
||||
#define _SET_INPUT(IO) CBI(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
|
||||
#define _SET_OUTPUT(IO) SBI(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
|
||||
#define _TOGGLE(IO) do {DIO ## IO ## _RPORT ^= _BV(DIO ## IO ## _PIN); } while (0)
|
||||
|
||||
#define _GET_INPUT(IO) !TEST(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
|
||||
#define _GET_OUTPUT(IO) TEST(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
|
||||
#define _GET_TIMER(IO) DIO ## IO ## _PWM
|
||||
#define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~_BV(DIO ## IO ## _PIN); } while (0)
|
||||
#define _SET_OUTPUT(IO) do {DIO ## IO ## _DDR |= _BV(DIO ## IO ## _PIN); } while (0)
|
||||
|
||||
#define READ(IO) _READ(IO)
|
||||
#define WRITE(IO,V) _WRITE(IO,V)
|
||||
#define TOGGLE(IO) _TOGGLE(IO)
|
||||
#define _GET_INPUT(IO) ((DIO ## IO ## _DDR & _BV(DIO ## IO ## _PIN)) == 0)
|
||||
#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & _BV(DIO ## IO ## _PIN)) != 0)
|
||||
#define _GET_TIMER(IO) (DIO ## IO ## _PWM)
|
||||
|
||||
#define SET_INPUT(IO) _SET_INPUT(IO)
|
||||
#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _WRITE(IO, HIGH); }while(0)
|
||||
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
|
||||
#define READ(IO) _READ(IO)
|
||||
#define WRITE(IO,V) _WRITE(IO,V)
|
||||
#define TOGGLE(IO) _TOGGLE(IO)
|
||||
|
||||
#define GET_INPUT(IO) _GET_INPUT(IO)
|
||||
#define GET_OUTPUT(IO) _GET_OUTPUT(IO)
|
||||
#define GET_TIMER(IO) _GET_TIMER(IO)
|
||||
#define SET_INPUT(IO) _SET_INPUT(IO)
|
||||
#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _WRITE(IO, HIGH); }while(0)
|
||||
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
|
||||
|
||||
#define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0)
|
||||
#define GET_INPUT(IO) _GET_INPUT(IO)
|
||||
#define GET_OUTPUT(IO) _GET_OUTPUT(IO)
|
||||
#define GET_TIMER(IO) _GET_TIMER(IO)
|
||||
|
||||
#define OUT_WRITE(IO, v) do{ SET_OUTPUT(IO); WRITE(IO, v); }while(0)
|
||||
|
||||
/**
|
||||
* Timer and Interrupt Control
|
||||
*/
|
||||
|
||||
// Waveform Generation Modes
|
||||
enum WaveGenMode : char {
|
||||
typedef enum {
|
||||
WGM_NORMAL, // 0
|
||||
WGM_PWM_PC_8, // 1
|
||||
WGM_PWM_PC_9, // 2
|
||||
@@ -126,18 +134,18 @@ enum WaveGenMode : char {
|
||||
WGM_reserved, // 13
|
||||
WGM_FAST_PWM_ICRn, // 14 COM OCnA
|
||||
WGM_FAST_PWM_OCRnA // 15 COM OCnA
|
||||
};
|
||||
} WaveGenMode;
|
||||
|
||||
// Compare Modes
|
||||
enum CompareMode : char {
|
||||
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
|
||||
enum ClockSource : char {
|
||||
typedef enum {
|
||||
CS_NONE, // 0
|
||||
CS_PRESCALER_1, // 1
|
||||
CS_PRESCALER_8, // 2
|
||||
@@ -146,10 +154,10 @@ enum ClockSource : char {
|
||||
CS_PRESCALER_1024, // 5
|
||||
CS_EXT_FALLING, // 6
|
||||
CS_EXT_RISING // 7
|
||||
};
|
||||
} ClockSource;
|
||||
|
||||
// Clock Sources (Timer 2 only)
|
||||
enum ClockSource2 : char {
|
||||
typedef enum {
|
||||
CS2_NONE, // 0
|
||||
CS2_PRESCALER_1, // 1
|
||||
CS2_PRESCALER_8, // 2
|
||||
@@ -158,10 +166,9 @@ enum ClockSource2 : char {
|
||||
CS2_PRESCALER_128, // 5
|
||||
CS2_PRESCALER_256, // 6
|
||||
CS2_PRESCALER_1024 // 7
|
||||
};
|
||||
} ClockSource2;
|
||||
|
||||
// Get interrupt bits in an orderly way
|
||||
// Ex: cs = GET_CS(0); coma1 = GET_COM(A,1);
|
||||
#define GET_WGM(T) (((TCCR##T##A >> WGM##T##0) & 0x3) | ((TCCR##T##B >> WGM##T##2 << 2) & 0xC))
|
||||
#define GET_CS(T) ((TCCR##T##B >> CS##T##0) & 0x7)
|
||||
#define GET_COM(T,Q) ((TCCR##T##Q >> COM##T##Q##0) & 0x3)
|
||||
@@ -176,7 +183,6 @@ enum ClockSource2 : char {
|
||||
#define GET_FOCC(T) GET_FOC(T,C)
|
||||
|
||||
// Set Wave Generation Mode bits
|
||||
// Ex: SET_WGM(5,CTC_ICRn);
|
||||
#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); \
|
||||
@@ -184,7 +190,6 @@ enum ClockSource2 : char {
|
||||
#define SET_WGM(T,V) _SET_WGM(T,WGM_##V)
|
||||
|
||||
// Set Clock Select bits
|
||||
// Ex: SET_CS3(PRESCALER_64);
|
||||
#define _SET_CS(T,V) (TCCR##T##B = (TCCR##T##B & ~(0x7 << CS##T##0)) | ((int(V) & 0x7) << CS##T##0))
|
||||
#define _SET_CS0(V) _SET_CS(0,V)
|
||||
#define _SET_CS1(V) _SET_CS(1,V)
|
||||
@@ -209,7 +214,6 @@ enum ClockSource2 : char {
|
||||
#define SET_CS(T,V) SET_CS##T(V)
|
||||
|
||||
// Set Compare Mode bits
|
||||
// Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET);
|
||||
#define _SET_COM(T,Q,V) (TCCR##T##Q = (TCCR##T##Q & ~(0x3 << COM##T##Q##0)) | (int(V) << COM##T##Q##0))
|
||||
#define SET_COM(T,Q,V) _SET_COM(T,Q,COM_##V)
|
||||
#define SET_COMA(T,V) SET_COM(T,A,V)
|
||||
@@ -218,15 +222,12 @@ enum ClockSource2 : char {
|
||||
#define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0)
|
||||
|
||||
// Set Noise Canceler bit
|
||||
// Ex: SET_ICNC(2,1)
|
||||
#define SET_ICNC(T,V) (TCCR##T##B = (V) ? TCCR##T##B | _BV(ICNC##T) : TCCR##T##B & ~_BV(ICNC##T))
|
||||
|
||||
// Set Input Capture Edge Select bit
|
||||
// Ex: SET_ICES(5,0)
|
||||
#define SET_ICES(T,V) (TCCR##T##B = (V) ? TCCR##T##B | _BV(ICES##T) : TCCR##T##B & ~_BV(ICES##T))
|
||||
|
||||
// Set Force Output Compare bit
|
||||
// Ex: SET_FOC(3,A,1)
|
||||
#define SET_FOC(T,Q,V) (TCCR##T##C = (V) ? TCCR##T##C | _BV(FOC##T##Q) : TCCR##T##C & ~_BV(FOC##T##Q))
|
||||
#define SET_FOCA(T,V) SET_FOC(T,A,V)
|
||||
#define SET_FOCB(T,V) SET_FOC(T,B,V)
|
||||
@@ -237,11 +238,11 @@ enum ClockSource2 : char {
|
||||
* PWM availability macros
|
||||
*/
|
||||
|
||||
// Determine which harware PWMs are already in use
|
||||
//find out which harware PWMs are already in use
|
||||
#if PIN_EXISTS(CONTROLLER_FAN)
|
||||
#define PWM_CHK_FAN_B(p) (p == CONTROLLER_FAN_PIN || p == E0_AUTO_FAN_PIN || p == E1_AUTO_FAN_PIN || p == E2_AUTO_FAN_PIN || p == E3_AUTO_FAN_PIN || p == E4_AUTO_FAN_PIN || p == CHAMBER_AUTO_FAN_PIN)
|
||||
#define PWM_CHK_FAN_B(p) (p == CONTROLLER_FAN_PIN || p == E0_AUTO_FAN_PIN || p == E1_AUTO_FAN_PIN || p == E2_AUTO_FAN_PIN || p == E3_AUTO_FAN_PIN || p == E4_AUTO_FAN_PIN)
|
||||
#else
|
||||
#define PWM_CHK_FAN_B(p) (p == E0_AUTO_FAN_PIN || p == E1_AUTO_FAN_PIN || p == E2_AUTO_FAN_PIN || p == E3_AUTO_FAN_PIN || p == E4_AUTO_FAN_PIN || p == CHAMBER_AUTO_FAN_PIN)
|
||||
#define PWM_CHK_FAN_B(p) (p == E0_AUTO_FAN_PIN || p == E1_AUTO_FAN_PIN || p == E2_AUTO_FAN_PIN || p == E3_AUTO_FAN_PIN || p == E4_AUTO_FAN_PIN)
|
||||
#endif
|
||||
|
||||
#if PIN_EXISTS(FAN) || PIN_EXISTS(FAN1) || PIN_EXISTS(FAN2)
|
||||
@@ -250,7 +251,7 @@ enum ClockSource2 : char {
|
||||
#elif PIN_EXISTS(FAN1)
|
||||
#define PWM_CHK_FAN_A(p) (p == FAN_PIN || p == FAN1_PIN)
|
||||
#else
|
||||
#define PWM_CHK_FAN_A(p) (p == FAN_PIN)
|
||||
#define PWM_CHK_FAN_A(p) p == FAN_PIN
|
||||
#endif
|
||||
#else
|
||||
#define PWM_CHK_FAN_A(p) false
|
||||
@@ -268,15 +269,15 @@ enum ClockSource2 : char {
|
||||
#define PWM_CHK_MOTOR_CURRENT(p) false
|
||||
#endif
|
||||
|
||||
#ifdef NUM_SERVOS
|
||||
#if defined(NUM_SERVOS)
|
||||
#if AVR_ATmega2560_FAMILY
|
||||
#define PWM_CHK_SERVO(p) (p == 5 || (NUM_SERVOS > 12 && p == 6) || (NUM_SERVOS > 24 && p == 46)) // PWMS 3A, 4A & 5A
|
||||
#define PWM_CHK_SERVO(p) ( p == 5 || NUM_SERVOS > 12 && p == 6 || NUM_SERVOS > 24 && p == 46) //PWMS 3A, 4A & 5A
|
||||
#elif AVR_ATmega2561_FAMILY
|
||||
#define PWM_CHK_SERVO(p) (p == 5) // PWM3A
|
||||
#define PWM_CHK_SERVO(p) p == 5 //PWM3A
|
||||
#elif AVR_ATmega1284_FAMILY
|
||||
#define PWM_CHK_SERVO(p) false
|
||||
#elif AVR_AT90USB1286_FAMILY
|
||||
#define PWM_CHK_SERVO(p) (p == 16) // PWM3A
|
||||
#define PWM_CHK_SERVO(p) p == 16 //PWM3A
|
||||
#elif AVR_ATmega328_FAMILY
|
||||
#define PWM_CHK_SERVO(p) false
|
||||
#endif
|
||||
@@ -300,15 +301,15 @@ enum ClockSource2 : char {
|
||||
// define which hardware PWMs are available for the current CPU
|
||||
// all timer 1 PWMS deleted from this list because they are never available
|
||||
#if AVR_ATmega2560_FAMILY
|
||||
#define PWM_PINS(p) ((p >= 2 && p <= 10) || p == 13 || p == 44 || p == 45 || p == 46)
|
||||
#define PWM_PINS(p) ((p >= 2 && p <= 10 ) || p == 13 || p == 44 || p == 45 || p == 46 )
|
||||
#elif AVR_ATmega2561_FAMILY
|
||||
#define PWM_PINS(p) ((p >= 2 && p <= 6) || p == 9)
|
||||
#define PWM_PINS(p) ((p >= 2 && p <= 6 ) || p == 9)
|
||||
#elif AVR_ATmega1284_FAMILY
|
||||
#define PWM_PINS(p) (p == 3 || p == 4 || p == 14 || p == 15)
|
||||
#define PWM_PINS(p) (p == 3 || p == 4 || p == 14 || p == 15)
|
||||
#elif AVR_AT90USB1286_FAMILY
|
||||
#define PWM_PINS(p) (p == 0 || p == 1 || p == 14 || p == 15 || p == 16 || p == 24)
|
||||
#define PWM_PINS(p) (p == 0 || p == 1 || p == 14 || p == 15 || p == 16 || p == 24)
|
||||
#elif AVR_ATmega328_FAMILY
|
||||
#define PWM_PINS(p) (p == 3 || p == 5 || p == 6 || p == 11)
|
||||
#define PWM_PINS(p) (p == 3 || p == 5 || p == 6 || p == 11)
|
||||
#else
|
||||
#error "unknown CPU"
|
||||
#endif
|
||||
@@ -316,4 +317,4 @@ enum ClockSource2 : char {
|
||||
// finally - the macro that tells us if a pin is an available hardware PWM
|
||||
#define USEABLE_HARDWARE_PWM(p) (PWM_PINS(p) && !PWM_CHK(p))
|
||||
|
||||
#endif // _FASTIO_ARDUINO_H_
|
||||
#endif // _FASTIO_ARDUINO_H
|
||||
|
||||
Reference in New Issue
Block a user