2016-03-25 07:19:46 +01:00
/**
2016-03-24 19:01:20 +01:00
* Marlin 3 D Printer Firmware
2019-02-12 22:06:53 +01:00
* Copyright ( C ) 2019 MarlinFirmware [ https : //github.com/MarlinFirmware/Marlin]
2016-03-24 19:01:20 +01:00
*
* Based on Sprinter and grbl .
* Copyright ( C ) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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 < http : //www.gnu.org/licenses/>.
*
*/
2018-11-04 09:25:55 +01:00
# pragma once
2016-03-24 19:01:20 +01:00
2016-03-25 07:19:46 +01:00
/**
2017-11-18 09:08:03 +01:00
* Fast I / O Routines for AVR
2017-05-22 20:12:52 +02:00
* Use direct port manipulation to save scads of processor time .
2017-11-18 09:08:03 +01:00
* Contributed by Triffid_Hunter and modified by Kliment , thinkyhead , Bob - the - Kuhn , et . al .
2017-04-20 20:20:08 +02:00
*/
2011-12-12 19:34:37 +01:00
# include <avr/io.h>
2017-09-06 13:28:32 +02:00
# include "../../core/macros.h"
2011-12-12 19:34:37 +01:00
2019-03-13 02:39:55 +01:00
# define AVR_AT90USB1286_FAMILY (defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1286P__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB646P__) || defined(__AVR_AT90USB647__))
2017-06-09 01:05:14 +02:00
# 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__))
2018-04-27 10:13:46 +02:00
# define AVR_ATmega328_FAMILY (defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__))
2017-06-09 01:05:14 +02:00
2017-05-22 20:12:52 +02:00
/**
* Include Ports and Functions
*/
2017-06-09 01:05:14 +02:00
# if AVR_ATmega328_FAMILY
2017-05-21 16:42:39 +02:00
# include "fastio_168.h"
2017-06-09 01:05:14 +02:00
# elif AVR_ATmega1284_FAMILY
2017-05-21 16:42:39 +02:00
# include "fastio_644.h"
2017-06-09 01:05:14 +02:00
# elif AVR_ATmega2560_FAMILY
2017-05-21 16:42:39 +02:00
# include "fastio_1280.h"
2017-06-09 01:05:14 +02:00
# elif AVR_AT90USB1286_FAMILY
# include "fastio_AT90USB.h"
# elif AVR_ATmega2561_FAMILY
2017-05-21 16:42:39 +02:00
# include "fastio_1281.h"
# else
2018-04-29 03:27:36 +02:00
# error "No FastIO definition for the selected AVR Board."
2017-05-21 16:42:39 +02:00
# endif
2016-03-25 07:19:46 +01:00
/**
2017-04-20 20:20:08 +02:00
* Magic I / O routines
*
* Now you can simply SET_OUTPUT ( PIN ) ; WRITE ( PIN , HIGH ) ; WRITE ( PIN , LOW ) ;
2017-05-22 20:12:52 +02:00
*
* Why double up on these macros ? see http : //gcc.gnu.org/onlinedocs/cpp/Stringification.html
2017-04-20 20:20:08 +02:00
*/
2018-04-24 20:45:43 +02:00
# define _READ(IO) TEST(DIO ## IO ## _RPORT, DIO ## IO ## _PIN)
2011-12-12 19:34:37 +01:00
2018-04-24 20:45:43 +02:00
# 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 )
2011-12-12 19:34:37 +01:00
2018-04-24 20:45:43 +02:00
# 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 )
2011-12-12 19:34:37 +01:00
2018-04-24 20:45:43 +02:00
# define _WRITE(IO,V) do{ if (&(DIO ## IO ## _RPORT) < (uint8_t*)0x100) _WRITE_NC(IO,V); else _WRITE_C(IO,V); }while(0)
2011-12-12 19:34:37 +01:00
2018-04-24 20:45:43 +02:00
# define _TOGGLE(IO) (DIO ## IO ## _RPORT = _BV(DIO ## IO ## _PIN))
2011-12-12 19:34:37 +01:00
2018-04-24 20:45:43 +02:00
# define _SET_INPUT(IO) CBI(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
# define _SET_OUTPUT(IO) SBI(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
2011-12-12 19:34:37 +01:00
2018-04-24 20:45:43 +02:00
# 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
2011-12-12 19:34:37 +01:00
2019-03-05 07:41:31 +01:00
// digitalRead/Write wrappers
# ifdef FASTIO_EXT_START
void extDigitalWrite ( const int8_t pin , const uint8_t state ) ;
uint8_t extDigitalRead ( const int8_t pin ) ;
# else
# define extDigitalWrite(IO,V) digitalWrite(IO,V)
# define extDigitalRead(IO) digitalRead(IO)
# endif
2018-04-24 20:45:43 +02:00
# define READ(IO) _READ(IO)
# define WRITE(IO,V) _WRITE(IO,V)
# define TOGGLE(IO) _TOGGLE(IO)
2011-12-12 19:34:37 +01:00
2018-04-24 20:45:43 +02:00
# 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)
2011-12-12 19:34:37 +01:00
2019-03-13 12:51:15 +01:00
# define SET_PWM(IO) SET_OUTPUT(IO)
2018-04-24 20:45:43 +02:00
# define GET_INPUT(IO) _GET_INPUT(IO)
# define GET_OUTPUT(IO) _GET_OUTPUT(IO)
# define GET_TIMER(IO) _GET_TIMER(IO)
2011-12-12 19:34:37 +01:00
2018-04-24 20:45:43 +02:00
# define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0)
2015-03-03 09:48:20 +01:00
2016-03-25 07:19:46 +01:00
/**
2017-04-24 21:04:46 +02:00
* Timer and Interrupt Control
2017-04-20 20:20:08 +02:00
*/
2011-12-12 19:34:37 +01:00
2017-04-20 20:20:08 +02:00
// Waveform Generation Modes
2018-04-18 00:26:57 +02:00
enum WaveGenMode : char {
2017-04-20 20:20:08 +02:00
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
2018-04-18 00:26:57 +02:00
} ;
2017-04-20 20:20:08 +02:00
2019-03-08 09:15:42 +01:00
// Wavefore Generation Modes (Timer 2 only)
enum WaveGenMode2 : char {
WGM2_NORMAL , // 0
WGM2_PWM_PC , // 1
WGM2_CTC_OCR2A , // 2
WGM2_FAST_PWM , // 3
WGM2_reserved_1 , // 4
WGM2_PWM_PC_OCR2A , // 5
WGM2_reserved_2 , // 6
WGM2_FAST_PWM_OCR2A , // 7
} ;
2017-04-20 20:20:08 +02:00
// Compare Modes
2018-04-18 00:26:57 +02:00
enum CompareMode : char {
2017-04-20 20:20:08 +02:00
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
2018-04-18 00:26:57 +02:00
} ;
2017-04-20 20:20:08 +02:00
// Clock Sources
2018-04-18 00:26:57 +02:00
enum ClockSource : char {
2017-04-20 20:20:08 +02:00
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
2018-04-18 00:26:57 +02:00
} ;
2017-04-20 20:20:08 +02:00
2017-04-24 21:04:46 +02:00
// Clock Sources (Timer 2 only)
2018-04-18 00:26:57 +02:00
enum ClockSource2 : char {
2017-04-24 21:04:46 +02:00
CS2_NONE , // 0
CS2_PRESCALER_1 , // 1
CS2_PRESCALER_8 , // 2
CS2_PRESCALER_32 , // 3
CS2_PRESCALER_64 , // 4
CS2_PRESCALER_128 , // 5
CS2_PRESCALER_256 , // 6
CS2_PRESCALER_1024 // 7
2018-04-18 00:26:57 +02:00
} ;
2017-04-24 21:04:46 +02:00
// Get interrupt bits in an orderly way
2017-09-06 13:28:32 +02:00
// Ex: cs = GET_CS(0); coma1 = GET_COM(A,1);
2017-04-24 21:04:46 +02:00
# 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)
# define GET_COMA(T) GET_COM(T,A)
# define GET_COMB(T) GET_COM(T,B)
# define GET_COMC(T) GET_COM(T,C)
# define GET_ICNC(T) (!!(TCCR##T##B & _BV(ICNC##T)))
# define GET_ICES(T) (!!(TCCR##T##B & _BV(ICES##T)))
# define GET_FOC(T,Q) (!!(TCCR##T##C & _BV(FOC##T##Q)))
# define GET_FOCA(T) GET_FOC(T,A)
# define GET_FOCB(T) GET_FOC(T,B)
# define GET_FOCC(T) GET_FOC(T,C)
// Set Wave Generation Mode bits
2017-09-06 13:28:32 +02:00
// Ex: SET_WGM(5,CTC_ICRn);
2017-04-24 21:04:46 +02:00
# define _SET_WGM(T,V) do{ \
2017-04-20 20:20:08 +02:00
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 )
2017-04-24 21:04:46 +02:00
# define SET_WGM(T,V) _SET_WGM(T,WGM_##V)
2019-03-26 07:03:23 +01:00
// Runtime (see set_pwm_frequency):
2019-03-08 09:15:42 +01:00
# define _SET_WGMnQ(TCCRnQ, V) do{ \
* ( TCCRnQ ) [ 0 ] = ( * ( TCCRnQ ) [ 0 ] & ~ ( 0x3 < < 0 ) ) | ( ( int ( V ) & 0x3 ) < < 0 ) ; \
* ( TCCRnQ ) [ 1 ] = ( * ( TCCRnQ ) [ 1 ] & ~ ( 0x3 < < 3 ) ) | ( ( ( int ( V ) > > 2 ) & 0x3 ) < < 3 ) ; \
} while ( 0 )
2017-04-24 21:04:46 +02:00
// Set Clock Select bits
2017-09-06 13:28:32 +02:00
// Ex: SET_CS3(PRESCALER_64);
2017-04-24 21:04:46 +02:00
# 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)
# ifdef TCCR2
# define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
# else
# define _SET_CS2(V) _SET_CS(2,V)
# endif
# define _SET_CS3(V) _SET_CS(3,V)
# define _SET_CS4(V) _SET_CS(4,V)
# define _SET_CS5(V) _SET_CS(5,V)
# define SET_CS0(V) _SET_CS0(CS_##V)
# define SET_CS1(V) _SET_CS1(CS_##V)
# ifdef TCCR2
# define SET_CS2(V) _SET_CS2(CS2_##V)
# else
# define SET_CS2(V) _SET_CS2(CS_##V)
# endif
# define SET_CS3(V) _SET_CS3(CS_##V)
# define SET_CS4(V) _SET_CS4(CS_##V)
# define SET_CS5(V) _SET_CS5(CS_##V)
# define SET_CS(T,V) SET_CS##T(V)
2019-03-26 07:03:23 +01:00
// Runtime (see set_pwm_frequency)
2019-03-08 09:15:42 +01:00
# define _SET_CSn(TCCRnQ, V) do{ \
( * ( TCCRnQ ) [ 1 ] = ( * ( TCCRnQ [ 1 ] ) & ~ ( 0x7 < < 0 ) ) | ( ( int ( V ) & 0x7 ) < < 0 ) ) ; \
} while ( 0 )
2017-04-24 21:04:46 +02:00
// Set Compare Mode bits
2017-09-06 13:28:32 +02:00
// Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET);
2017-04-24 21:04:46 +02:00
# 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)
2017-04-20 20:20:08 +02:00
# define SET_COMA(T,V) SET_COM(T,A,V)
# define SET_COMB(T,V) SET_COM(T,B,V)
2017-04-24 21:04:46 +02:00
# define SET_COMC(T,V) SET_COM(T,C,V)
# define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0)
2019-03-26 07:03:23 +01:00
// Runtime (see set_pwm_duty)
2019-03-08 09:15:42 +01:00
# define _SET_COMnQ(TCCRnQ, Q, V) do{ \
( * ( TCCRnQ ) [ 0 ] = ( * ( TCCRnQ ) [ 0 ] & ~ ( 0x3 < < ( 6 - 2 * ( Q ) ) ) ) | ( int ( V ) < < ( 6 - 2 * ( Q ) ) ) ) ; \
} while ( 0 )
// Set OCRnQ register
2019-03-26 07:03:23 +01:00
// Runtime (see set_pwm_duty):
2019-03-08 09:15:42 +01:00
# define _SET_OCRnQ(OCRnQ, Q, V) do{ \
( * ( OCRnQ ) [ ( Q ) ] = ( 0x0000 ) | ( int ( V ) & 0xFFFF ) ) ; \
} while ( 0 )
// Set ICRn register (one per timer)
2019-03-26 07:03:23 +01:00
// Runtime (see set_pwm_frequency)
2019-03-08 09:15:42 +01:00
# define _SET_ICRn(ICRn, V) do{ \
( * ( ICRn ) = ( 0x0000 ) | ( int ( V ) & 0xFFFF ) ) ; \
} while ( 0 )
2017-04-24 21:04:46 +02:00
// Set Noise Canceler bit
2017-09-06 13:28:32 +02:00
// Ex: SET_ICNC(2,1)
2017-04-24 21:04:46 +02:00
# 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
2017-09-06 13:28:32 +02:00
// Ex: SET_ICES(5,0)
2017-04-24 21:04:46 +02:00
# define SET_ICES(T,V) (TCCR##T##B = (V) ? TCCR##T##B | _BV(ICES##T) : TCCR##T##B & ~_BV(ICES##T))
2017-04-20 20:20:08 +02:00
2017-04-24 21:04:46 +02:00
// Set Force Output Compare bit
2017-09-06 13:28:32 +02:00
// Ex: SET_FOC(3,A,1)
2017-04-24 21:04:46 +02:00
# 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)
# define SET_FOCC(T,V) SET_FOC(T,C,V)
2017-04-20 20:20:08 +02:00
2017-05-19 22:21:43 +02:00
/**
* PWM availability macros
*/
2018-04-18 00:26:57 +02:00
// Determine which harware PWMs are already in use
2017-05-19 22:21:43 +02:00
# if PIN_EXISTS(CONTROLLER_FAN)
2019-03-13 12:51:15 +01:00
# 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 == E5_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN)
2017-05-19 22:21:43 +02:00
# else
2019-03-13 12:51:15 +01:00
# 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 == E5_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN)
2017-05-19 22:21:43 +02:00
# endif
2019-03-17 05:43:06 +01:00
# if ANY_PIN(FAN, FAN1, FAN2)
2017-05-19 22:21:43 +02:00
# if PIN_EXISTS(FAN2)
2019-03-13 12:51:15 +01:00
# define PWM_CHK_FAN_A(P) (P == FAN_PIN || P == FAN1_PIN || P == FAN2_PIN)
2017-05-19 22:21:43 +02:00
# elif PIN_EXISTS(FAN1)
2019-03-13 12:51:15 +01:00
# define PWM_CHK_FAN_A(P) (P == FAN_PIN || P == FAN1_PIN)
2017-05-19 22:21:43 +02:00
# else
2019-03-13 12:51:15 +01:00
# define PWM_CHK_FAN_A(P) (P == FAN_PIN)
2017-05-19 22:21:43 +02:00
# endif
# else
2019-03-13 12:51:15 +01:00
# define PWM_CHK_FAN_A(P) false
2017-05-19 22:21:43 +02:00
# endif
# if HAS_MOTOR_CURRENT_PWM
# if PIN_EXISTS(MOTOR_CURRENT_PWM_XY)
2019-03-13 12:51:15 +01:00
# define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E || P == MOTOR_CURRENT_PWM_Z || P == MOTOR_CURRENT_PWM_XY)
2017-05-19 22:21:43 +02:00
# elif PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
2019-03-13 12:51:15 +01:00
# define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E || P == MOTOR_CURRENT_PWM_Z)
2017-05-19 22:21:43 +02:00
# else
2019-03-13 12:51:15 +01:00
# define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E)
2017-05-19 22:21:43 +02:00
# endif
# else
2019-03-13 12:51:15 +01:00
# define PWM_CHK_MOTOR_CURRENT(P) false
2017-05-19 22:21:43 +02:00
# endif
2017-06-18 01:36:10 +02:00
# ifdef NUM_SERVOS
2017-05-19 22:21:43 +02:00
# if AVR_ATmega2560_FAMILY
2019-03-13 12:51:15 +01:00
# define PWM_CHK_SERVO(P) (P == 5 || (NUM_SERVOS > 12 && P == 6) || (NUM_SERVOS > 24 && P == 46)) // PWMS 3A, 4A & 5A
2017-05-19 22:21:43 +02:00
# elif AVR_ATmega2561_FAMILY
2019-03-13 12:51:15 +01:00
# define PWM_CHK_SERVO(P) (P == 5) // PWM3A
2017-05-19 22:21:43 +02:00
# elif AVR_ATmega1284_FAMILY
2019-03-13 12:51:15 +01:00
# define PWM_CHK_SERVO(P) false
2017-05-19 22:21:43 +02:00
# elif AVR_AT90USB1286_FAMILY
2019-03-13 12:51:15 +01:00
# define PWM_CHK_SERVO(P) (P == 16) // PWM3A
2017-05-19 22:21:43 +02:00
# elif AVR_ATmega328_FAMILY
2019-03-13 12:51:15 +01:00
# define PWM_CHK_SERVO(P) false
2017-05-19 22:21:43 +02:00
# endif
# else
2019-03-13 12:51:15 +01:00
# define PWM_CHK_SERVO(P) false
2017-05-19 22:21:43 +02:00
# endif
# if ENABLED(BARICUDA)
# if HAS_HEATER_1 && HAS_HEATER_2
2019-03-13 12:51:15 +01:00
# define PWM_CHK_HEATER(P) (P == HEATER_1_PIN || P == HEATER_2_PIN)
2017-05-19 22:21:43 +02:00
# elif HAS_HEATER_1
2019-03-13 12:51:15 +01:00
# define PWM_CHK_HEATER(P) (P == HEATER_1_PIN)
2017-05-19 22:21:43 +02:00
# endif
# else
2019-03-13 12:51:15 +01:00
# define PWM_CHK_HEATER(P) false
2017-05-19 22:21:43 +02:00
# endif
2019-03-13 12:51:15 +01:00
# define PWM_CHK(P) (PWM_CHK_HEATER(P) || PWM_CHK_SERVO(P) || PWM_CHK_MOTOR_CURRENT(P) || PWM_CHK_FAN_A(P) || PWM_CHK_FAN_B(P))
2017-05-19 22:21:43 +02:00
// 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
2019-03-13 12:51:15 +01:00
# define PWM_PIN(P) ((P >= 2 && P <= 10) || P == 13 || P == 44 || P == 45 || P == 46)
2017-05-19 22:21:43 +02:00
# elif AVR_ATmega2561_FAMILY
2019-03-13 12:51:15 +01:00
# define PWM_PIN(P) ((P >= 2 && P <= 6) || P == 9)
2017-05-19 22:21:43 +02:00
# elif AVR_ATmega1284_FAMILY
2019-03-13 12:51:15 +01:00
# define PWM_PIN(P) (P == 3 || P == 4 || P == 14 || P == 15)
2017-05-19 22:21:43 +02:00
# elif AVR_AT90USB1286_FAMILY
2019-03-13 12:51:15 +01:00
# define PWM_PIN(P) (P == 0 || P == 1 || P == 14 || P == 15 || P == 16 || P == 24)
2017-05-19 22:21:43 +02:00
# elif AVR_ATmega328_FAMILY
2019-03-13 12:51:15 +01:00
# define PWM_PIN(P) (P == 3 || P == 5 || P == 6 || P == 11)
2017-05-19 22:21:43 +02:00
# else
# error "unknown CPU"
# endif
2019-03-13 06:11:35 +01:00
# define USEABLE_HARDWARE_PWM(P) (PWM_PIN(P) && !PWM_CHK(P))