2074 أسطر
68 KiB
C
2074 أسطر
68 KiB
C
// in vim, :set ts=2 sts=2 sw=2 et fdm=marker
|
|
|
|
// EnableInterrupt, a library by GreyGnome. Copyright 2014-2015 by Michael Anthony Schwager.
|
|
|
|
/*
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
// Many definitions in /usr/avr/include/avr/io.h
|
|
|
|
#ifndef EnableInterrupt_h
|
|
#define EnableInterrupt_h
|
|
#include <Arduino.h>
|
|
|
|
// Function Prototypes (comment) /*{{{*/
|
|
/* *************************************************************************************
|
|
// *************************************************************************************
|
|
// Function Prototypes *****************************************************************
|
|
// *************************************************************************************
|
|
// *************************************************************************************
|
|
// *** These are the only functions the end user (programmer) needs to consider. ***
|
|
// *** This means you! ***
|
|
// *************************************************************************************
|
|
*//*}}}*/
|
|
|
|
// Arduino Due (not Duemilanove) and Zero macros. Easy-peasy.
|
|
// Zero uses the __SAMD21G18A__ processor macro (2015-10-13) but we will use this handy macro, to
|
|
// avoid breaking the library over tiny changes.
|
|
#if defined __SAM3U4E__ || defined __SAM3X8E__ || defined __SAM3X8H__ || defined ARDUINO_SAMD_ZERO || defined __SAMD21G18A__ || defined __SAMD21J18A__ /*{{{*/
|
|
#ifdef NEEDFORSPEED
|
|
#error Due and Zero are already fast; the NEEDFORSPEED definition does not make sense on it.
|
|
#endif
|
|
#define enableInterrupt(pin,userFunc,mode) attachInterrupt(pin, userFunc,mode)
|
|
#define disableInterrupt(pin) detachInterrupt(pin)/*}}}*/
|
|
#else
|
|
|
|
// Usage: (comment) /*{{{*/
|
|
/* enableInterrupt- Sets up an interrupt on a selected Arduino pin.
|
|
* or
|
|
* enableInterruptFast- When used with the NEEDFORSPEED macro, sets up an interrupt on a selected Arduino pin.
|
|
*
|
|
* Usage:
|
|
* enableInterrupt(uint8_t pinNumber, void (*userFunction)(void), uint8_t mode);
|
|
* or
|
|
* enableInterrupt(uint8_t interruptDesignator, void (*userFunction)(void), uint8_t mode);
|
|
*
|
|
* For HiSpeed mode,
|
|
* enableInterruptFast(uint8_t pinNumber, uint8_t mode);
|
|
* or
|
|
* enableInterruptFast(uint8_t interruptDesignator, uint8_t mode);
|
|
*
|
|
* ---------------------------------------------------------------------------------------
|
|
*
|
|
* disableInterrupt- Disables interrupt on a selected Arduino pin.
|
|
*
|
|
* Usage:
|
|
*
|
|
* disableInterrupt(uint8_t pinNumber);
|
|
* or
|
|
* disableInterrupt(uint8_t interruptDesignator);
|
|
*
|
|
* ---------------------------------------------------------------------------------------
|
|
*
|
|
* interruptDesignator: Essentially this is an Arduino pin, and if that's all you want to give
|
|
* the function, it will work just fine. Why is it called an "interruptDesignator", then? Because
|
|
* there's a twist: You can perform a bitwise "and" with the pin number and PINCHANGEINTERRUPT
|
|
* to specify that you want to use a Pin Change Interrupt type of interrupt on those pins that
|
|
* support both Pin Change and External Interrupts. Otherwise, the library will choose whatever
|
|
* interrupt type (External, or Pin Change) normally applies to that pin, with priority to
|
|
* External Interrupt.
|
|
*
|
|
* The interruptDesignator is required because on the ATmega328 processor pins 2 and 3 support
|
|
* ''either'' pin change or * external interrupts. On 644/1284-based systems, pin change interrupts
|
|
* are supported on all pins and external interrupts are supported on pins 2, 10, and 11.
|
|
* Otherwise, each pin only supports a single type of interrupt and the
|
|
* PINCHANGEINTERRUPT scheme changes nothing. This means you can ignore this whole discussion
|
|
* for ATmega2560- or ATmega32U4-based Arduinos. You can probably safely ignore it for
|
|
* ATmega328-based Arduinos, too.
|
|
*//*}}}*/
|
|
|
|
void enableInterrupt(uint8_t interruptDesignator, void (*userFunction)(void), uint8_t mode);
|
|
void disableInterrupt(uint8_t interruptDesignator);
|
|
void bogusFunctionPlaceholder(void);
|
|
#ifdef NEEDFORSPEED
|
|
#undef enableInterruptFast
|
|
// enableInterruptFast(uint8_t interruptDesignator, uint8_t mode);
|
|
#define enableInterruptFast(x, y) enableInterrupt(x, bogusFunctionPlaceholder, y)
|
|
#endif
|
|
|
|
// *************************************************************************************
|
|
// End Function Prototypes *************************************************************
|
|
// *************************************************************************************
|
|
|
|
#undef PINCHANGEINTERRUPT
|
|
#define PINCHANGEINTERRUPT 0x80
|
|
|
|
#undef attachPinChangeInterrupt
|
|
#undef detachPinChangeInterrupt
|
|
#define detachPinChangeInterrupt(pin) disableInterrupt(pin)
|
|
#define attachPinChangeInterrupt(pin,userFunc,mode) enableInterrupt(pin, userFunc, mode)
|
|
|
|
#ifdef LIBCALL_ENABLEINTERRUPT // LIBCALL_ENABLEINTERRUPT ****************************************
|
|
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
extern volatile uint8_t arduinoInterruptedPin;
|
|
extern volatile uint8_t arduinoPinState;
|
|
#endif
|
|
|
|
#else
|
|
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
volatile uint8_t arduinoInterruptedPin=0;
|
|
volatile uint8_t arduinoPinState=0;
|
|
#endif
|
|
|
|
|
|
#ifdef NEEDFORSPEED
|
|
void bogusFunctionPlaceholder(void) {
|
|
}
|
|
#include "utility/ei_pindefs_speed.h"
|
|
#endif
|
|
|
|
/* Arduino pin to ATmega port translaton is found doing digital_pin_to_port_PGM[] */
|
|
/* Arduino pin to PCMSKx bitmask is found by doing digital_pin_to_bit_mask_PGM[] */
|
|
/* ...except for PortJ, which is shifted left 1 bit in PCI1 */
|
|
volatile uint8_t *pcmsk;
|
|
|
|
// Arduino.h has these, but the block is surrounded by #ifdef ARDUINO_MAIN
|
|
#define PA 1
|
|
#define PB 2
|
|
#define PC 3
|
|
#define PD 4
|
|
#define PE 5
|
|
#define PF 6
|
|
#define PG 7
|
|
#define PH 8
|
|
#define PJ 10
|
|
#define PK 11
|
|
#define PL 12
|
|
|
|
typedef void (*interruptFunctionType)(void);
|
|
|
|
// ===========================================================================================
|
|
// CHIP SPECIFIC DATA STRUCTURES =============================================================
|
|
// ===========================================================================================
|
|
|
|
/* UNO SERIES *************************************************************************/
|
|
/* UNO SERIES *************************************************************************/
|
|
/* UNO SERIES *************************************************************************/
|
|
#if defined __AVR_ATmega168__ || defined __AVR_ATmega168A__ || defined __AVR_ATmega168P__ || \
|
|
defined __AVR_ATmega168PA__ || defined __AVR_ATmega328__ || defined __AVR_ATmega328P__
|
|
#define ARDUINO_328 /*{{{*/
|
|
#define EI_NOTPORTA
|
|
#define EI_NOTPORTJ
|
|
#define EI_NOTPORTK /*}}}*/
|
|
|
|
#if defined EI_NOTPINCHANGE /*{{{*/
|
|
#ifndef EI_NOTPORTB
|
|
#define EI_NOTPORTB
|
|
#endif
|
|
#ifndef EI_NOTPORTC
|
|
#define EI_NOTPORTC
|
|
#endif
|
|
#ifndef EI_NOTPORTD
|
|
#define EI_NOTPORTD
|
|
#endif
|
|
#endif // defined EI_NOTPINCHANGE
|
|
|
|
#ifndef NEEDFORSPEED
|
|
|
|
#define ARDUINO_PIN_B0 8
|
|
#define ARDUINO_PIN_B1 9
|
|
#define ARDUINO_PIN_B2 10
|
|
#define ARDUINO_PIN_B3 11
|
|
#define ARDUINO_PIN_B4 12
|
|
#define ARDUINO_PIN_B5 13
|
|
#define ARDUINO_PIN_C0 14
|
|
#define ARDUINO_PIN_C1 15
|
|
#define ARDUINO_PIN_C2 16
|
|
#define ARDUINO_PIN_C3 17
|
|
#define ARDUINO_PIN_C4 18
|
|
#define ARDUINO_PIN_C5 19
|
|
#define ARDUINO_PIN_D0 0
|
|
#define ARDUINO_PIN_D1 1
|
|
#define ARDUINO_PIN_D2 2
|
|
#define ARDUINO_PIN_D3 3
|
|
#define ARDUINO_PIN_D4 4
|
|
#define ARDUINO_PIN_D5 5
|
|
#define ARDUINO_PIN_D6 6
|
|
#define ARDUINO_PIN_D7 7
|
|
|
|
const uint8_t PROGMEM digital_pin_to_port_bit_number_PGM[] = {
|
|
0, // 0 == port D, 0
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
0, // 8 == port B, 0
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
0, // 14 == port C, 0
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5
|
|
};
|
|
|
|
#if ! defined(EI_NOTEXTERNAL) && ! defined(EI_NOTINT0) && ! defined (EI_NOTINT1)
|
|
interruptFunctionType functionPointerArrayEXTERNAL[2];
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTB
|
|
// 2 of the interrupts are unsupported on Arduino UNO.
|
|
struct functionPointersPortB {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
interruptFunctionType pinFour;
|
|
interruptFunctionType pinFive;
|
|
};
|
|
typedef struct functionPointersPortB functionPointersPortB;
|
|
|
|
functionPointersPortB portBFunctions = { NULL, NULL, NULL, NULL, NULL, NULL };
|
|
|
|
#endif // EI_NOTPORTB
|
|
|
|
#ifndef EI_NOTPORTC
|
|
// 1 of the interrupts are used as RESET on Arduino UNO.
|
|
struct functionPointersPortC {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
interruptFunctionType pinFour;
|
|
interruptFunctionType pinFive;
|
|
};
|
|
typedef struct functionPointersPortC functionPointersPortC;
|
|
|
|
functionPointersPortC portCFunctions = { NULL, NULL, NULL, NULL, NULL, NULL };
|
|
|
|
#endif // EI_NOTPORTC
|
|
|
|
#ifndef EI_NOTPORTD
|
|
// 1 of the interrupts are used as RESET on Arduino UNO.
|
|
struct functionPointersPortD {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
interruptFunctionType pinFour;
|
|
interruptFunctionType pinFive;
|
|
interruptFunctionType pinSix;
|
|
interruptFunctionType pinSeven;
|
|
};
|
|
typedef struct functionPointersPortD functionPointersPortD;
|
|
|
|
functionPointersPortD portDFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
|
|
#endif // EI_NOTPORTD
|
|
#endif // NEEDFORSPEED
|
|
|
|
// For Pin Change Interrupts; since we're duplicating FALLING and RISING in software,
|
|
// we have to know how the ports were defined.
|
|
#ifndef EI_NOTPORTB
|
|
volatile uint8_t risingPinsPORTB=0;
|
|
volatile uint8_t fallingPinsPORTB=0;
|
|
// for the saved state of the ports
|
|
static volatile uint8_t portSnapshotB;
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTC
|
|
volatile uint8_t risingPinsPORTC=0;
|
|
volatile uint8_t fallingPinsPORTC=0;
|
|
static volatile uint8_t portSnapshotC;
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTD
|
|
volatile uint8_t risingPinsPORTD=0;
|
|
volatile uint8_t fallingPinsPORTD=0;
|
|
static volatile uint8_t portSnapshotD;
|
|
#endif
|
|
|
|
// the PCINT?_vect's are defined in the avr.h files, like iom328p.h
|
|
#define PORTB_VECT PCINT0_vect
|
|
#define PORTC_VECT PCINT1_vect
|
|
#define PORTD_VECT PCINT2_vect/*}}}*/
|
|
|
|
/* MEGA2560/1280/640 SERIES ************************************************************************/
|
|
/* MEGA2560/1280/640 SERIES ************************************************************************/
|
|
/* MEGA2560/1280/640 SERIES ************************************************************************/
|
|
#elif defined __AVR_ATmega640__ || defined __AVR_ATmega2560__ || defined __AVR_ATmega1280__
|
|
#define ARDUINO_MEGA /*{{{*/
|
|
#define EI_NOTPORTA
|
|
#define EI_NOTPORTC
|
|
#define EI_NOTPORTD /*}}}*/
|
|
|
|
#if defined EI_NOTPINCHANGE/*{{{*/
|
|
#ifndef EI_NOTPORTB
|
|
#define EI_NOTPORTB
|
|
#endif
|
|
#ifndef EI_NOTPORTJ
|
|
#define EI_NOTPORTJ
|
|
#endif
|
|
#ifndef EI_NOTPORTK
|
|
#define EI_NOTPORTK
|
|
#endif
|
|
#endif
|
|
|
|
volatile uint8_t portJPCMSK=0; // This is a shifted version of PCMSK for PortJ, so I
|
|
// don't have to perform a shift in the IRQ.
|
|
|
|
#ifndef NEEDFORSPEED
|
|
// Pin change interrupts
|
|
#define ARDUINO_PIN_B0 53
|
|
#define ARDUINO_PIN_B1 52
|
|
#define ARDUINO_PIN_B2 51
|
|
#define ARDUINO_PIN_B3 50
|
|
#define ARDUINO_PIN_B4 10
|
|
#define ARDUINO_PIN_B5 11
|
|
#define ARDUINO_PIN_B6 12
|
|
#define ARDUINO_PIN_B7 13
|
|
#define ARDUINO_PIN_J0 15
|
|
#define ARDUINO_PIN_J1 14
|
|
// "fake" pins
|
|
#define ARDUINO_PIN_J2 70
|
|
#define ARDUINO_PIN_J3 71
|
|
#define ARDUINO_PIN_J4 72
|
|
#define ARDUINO_PIN_J5 73
|
|
#define ARDUINO_PIN_J6 74
|
|
|
|
#define ARDUINO_PIN_K0 62
|
|
#define ARDUINO_PIN_K1 63
|
|
#define ARDUINO_PIN_K2 64
|
|
#define ARDUINO_PIN_K3 65
|
|
#define ARDUINO_PIN_K4 66
|
|
#define ARDUINO_PIN_K5 67
|
|
#define ARDUINO_PIN_K6 68
|
|
#define ARDUINO_PIN_K7 69
|
|
|
|
#define ARDUINO_PIN_D0 21
|
|
#define ARDUINO_PIN_D1 20
|
|
#define ARDUINO_PIN_D2 19
|
|
#define ARDUINO_PIN_D3 18
|
|
#define ARDUINO_PIN_E4 2
|
|
#define ARDUINO_PIN_E5 3
|
|
#define ARDUINO_PIN_E6 75
|
|
#define ARDUINO_PIN_E7 76
|
|
|
|
const uint8_t PROGMEM digital_pin_to_port_bit_number_PGM[] = {
|
|
0, // PE0 pin: 0
|
|
1, // PE1 pin: 1
|
|
4, // PE4 pin: 2
|
|
5, // PE5 pin: 3
|
|
5, // PG5 pin: 4
|
|
3, // PE3 pin: 5
|
|
3, // PH3 pin: 6
|
|
4, // PH4 pin: 7
|
|
5, // PH5 pin: 8
|
|
6, // PH6 pin: 9
|
|
4, // PB4 pin: 10
|
|
5, // PB5 pin: 11
|
|
6, // PB6 pin: 12
|
|
7, // PB7 pin: 13
|
|
1, // PJ1 pin: 14
|
|
0, // PJ0 pin: 15
|
|
1, // PH1 pin: 16
|
|
0, // PH0 pin: 17
|
|
3, // PD3 pin: 18
|
|
2, // PD2 pin: 19
|
|
1, // PD1 pin: 20
|
|
0, // PD0 pin: 21
|
|
0, // PA0 pin: 22
|
|
1, // PA1 pin: 23
|
|
2, // PA2 pin: 24
|
|
3, // PA3 pin: 25
|
|
4, // PA4 pin: 26
|
|
5, // PA5 pin: 27
|
|
6, // PA6 pin: 28
|
|
7, // PA7 pin: 29
|
|
7, // PC7 pin: 30
|
|
6, // PC6 pin: 31
|
|
5, // PC5 pin: 32
|
|
4, // PC4 pin: 33
|
|
3, // PC3 pin: 34
|
|
2, // PC2 pin: 35
|
|
1, // PC1 pin: 36
|
|
0, // PC0 pin: 37
|
|
7, // PD7 pin: 38
|
|
2, // PG2 pin: 39
|
|
1, // PG1 pin: 40
|
|
0, // PG0 pin: 41
|
|
7, // PL7 pin: 42
|
|
6, // PL6 pin: 43
|
|
5, // PL5 pin: 44
|
|
4, // PL4 pin: 45
|
|
3, // PL3 pin: 46
|
|
2, // PL2 pin: 47
|
|
1, // PL1 pin: 48
|
|
0, // PL0 pin: 49
|
|
3, // PB3 pin: 50
|
|
2, // PB2 pin: 51
|
|
1, // PB1 pin: 52
|
|
0, // PB0 pin: 53
|
|
0, // PF0 pin: 54
|
|
1, // PF1 pin: 55
|
|
2, // PF2 pin: 56
|
|
3, // PF3 pin: 57
|
|
4, // PF4 pin: 58
|
|
5, // PF5 pin: 59
|
|
6, // PF6 pin: 60
|
|
7, // PF7 pin: 61
|
|
0, // PK0 pin: 62
|
|
1, // PK1 pin: 63
|
|
2, // PK2 pin: 64
|
|
3, // PK3 pin: 65
|
|
4, // PK4 pin: 66
|
|
5, // PK5 pin: 67
|
|
6, // PK6 pin: 68
|
|
7, // PK7 pin: 69
|
|
2, // PJ2 pin: fake70, trick to allow software interrupts on Port J. PJ2
|
|
3, // PJ3 pin: fake71 PJ3
|
|
4, // PJ4 pin: fake72 PJ4
|
|
5, // PJ5 pin: fake73 PJ5
|
|
6, // PJ6 pin: fake74 PJ6
|
|
6, // PE6 pin: fake75 PE6
|
|
7 // PE7 pin: fake76 PE7
|
|
};
|
|
|
|
#if ! defined(EI_NOTEXTERNAL) && ! defined(EI_NOTINT0) && ! defined(EI_NOTINT1) && ! defined(EI_NOTINT2) && ! defined(EI_NOTINT3) && ! defined(EI_NOTINT4) && ! defined(EI_NOTINT5) && ! defined(EI_NOTINT6) && ! defined(EI_NOTINT7)
|
|
interruptFunctionType functionPointerArrayEXTERNAL[8];
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTB
|
|
struct functionPointersPortB {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
interruptFunctionType pinFour;
|
|
interruptFunctionType pinFive;
|
|
interruptFunctionType pinSix;
|
|
interruptFunctionType pinSeven;
|
|
};
|
|
typedef struct functionPointersPortB functionPointersPortB;
|
|
|
|
functionPointersPortB portBFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTJ
|
|
// only 7 pins total of port J are supported as interrupts on the ATmega2560,
|
|
// and only PJ0 and 1 are supported on the Arduino MEGA.
|
|
// For PCI1 the 0th bit is PE0. PJ2-6 are not exposed on the Arduino pins, but
|
|
// we will support them anyway. There are clones that provide them, and users may
|
|
// solder in their own connections (...go, Makers!)
|
|
struct functionPointersPortJ {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
interruptFunctionType pinFour;
|
|
interruptFunctionType pinFive;
|
|
interruptFunctionType pinSix;
|
|
};
|
|
typedef struct functionPointersPortJ functionPointersPortJ;
|
|
|
|
functionPointersPortJ portJFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTK
|
|
struct functionPointersPortK {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
interruptFunctionType pinFour;
|
|
interruptFunctionType pinFive;
|
|
interruptFunctionType pinSix;
|
|
interruptFunctionType pinSeven;
|
|
};
|
|
typedef struct functionPointersPortK functionPointersPortK;
|
|
|
|
functionPointersPortK portKFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
#endif
|
|
#endif // ifndef NEEDFORSPEED
|
|
|
|
// For Pin Change Interrupts; since we're duplicating FALLING and RISING in software,
|
|
// we have to know how we were defined.
|
|
#ifndef EI_NOTPORTB
|
|
volatile uint8_t risingPinsPORTB=0;
|
|
volatile uint8_t fallingPinsPORTB=0;
|
|
static volatile uint8_t portSnapshotB;
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTJ
|
|
volatile uint8_t risingPinsPORTJ=0;
|
|
volatile uint8_t fallingPinsPORTJ=0;
|
|
static volatile uint8_t portSnapshotJ;
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTK
|
|
volatile uint8_t risingPinsPORTK=0;
|
|
volatile uint8_t fallingPinsPORTK=0;
|
|
static volatile uint8_t portSnapshotK;
|
|
#endif
|
|
|
|
#define PORTB_VECT PCINT0_vect
|
|
#define PORTJ_VECT PCINT1_vect
|
|
#define PORTK_VECT PCINT2_vect
|
|
/*}}}*/
|
|
|
|
/* MEGA2561/1281 SERIES ************************************************************************/
|
|
/* MEGA2561/1281 SERIES ************************************************************************/
|
|
/* MEGA2561/1281 SERIES ************************************************************************/
|
|
#elif defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
|
|
#define ARDUINO_MEGA /*{{{*/
|
|
#define EI_NOTPORTA
|
|
#define EI_NOTPORTC
|
|
#define EI_NOTPORTD
|
|
#define EI_NOTPORTJ
|
|
#define EI_NOTPORTK /*}}}*/
|
|
|
|
#if defined EI_NOTPINCHANGE/*{{{*/
|
|
#ifndef EI_NOTPORTB
|
|
#define EI_NOTPORTB
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef NEEDFORSPEED
|
|
// Pin change interrupts
|
|
#define ARDUINO_PIN_B0 8
|
|
#define ARDUINO_PIN_B1 9
|
|
#define ARDUINO_PIN_B2 10
|
|
#define ARDUINO_PIN_B3 11
|
|
#define ARDUINO_PIN_B4 12
|
|
#define ARDUINO_PIN_B5 13
|
|
#define ARDUINO_PIN_B6 14
|
|
#define ARDUINO_PIN_B7 15
|
|
|
|
const uint8_t PROGMEM digital_pin_to_port_bit_number_PGM[] = {
|
|
0, // PE0 pin: 0
|
|
1, // PE1 pin: 1
|
|
2, // PE2 pin: 2
|
|
3, // PE3 pin: 3
|
|
4, // PE4 pin: 4
|
|
5, // PE5 pin: 5
|
|
6, // PE6 pin: 6
|
|
7, // PE7 pin: 7
|
|
0, // PB0 pin: 8
|
|
1, // PB1 pin: 9
|
|
2, // PB2 pin: 10
|
|
3, // PB3 pin: 11
|
|
4, // PB4 pin: 12
|
|
5, // PB5 pin: 13
|
|
6, // PB6 pin: 14
|
|
7, // PB7 pin: 15
|
|
3, // PG3 pin: 16
|
|
4, // PG4 pin: 17
|
|
0, // PD0 pin: 18
|
|
1, // PD1 pin: 19
|
|
2, // PD2 pin: 20
|
|
3, // PD3 pin: 21
|
|
4, // PD4 pin: 22
|
|
5, // PD5 pin: 23
|
|
6, // PD6 pin: 24
|
|
7, // PD7 pin: 25
|
|
0, // PG0 pin: 26
|
|
1, // PG1 pin: 27
|
|
0, // PC0 pin: 28
|
|
1, // PC1 pin: 29
|
|
2, // PC2 pin: 30
|
|
3, // PC3 pin: 31
|
|
4, // PC4 pin: 32
|
|
5, // PC5 pin: 33
|
|
6, // PC6 pin: 34
|
|
7, // PC7 pin: 35
|
|
2, // PG2 pin: 36
|
|
7, // PA7 pin: 37
|
|
6, // PA6 pin: 38
|
|
5, // PA5 pin: 39
|
|
4, // PA4 pin: 40
|
|
3, // PA3 pin: 41
|
|
2, // PA2 pin: 42
|
|
1, // PA1 pin: 43
|
|
0, // PA0 pin: 44
|
|
0, // PF0 pin: 45
|
|
1, // PF1 pin: 46
|
|
2, // PF2 pin: 47
|
|
3, // PF3 pin: 48
|
|
4, // PF4 pin: 49
|
|
5, // PF5 pin: 50
|
|
6, // PF6 pin: 51
|
|
7, // PF7 pin: 52
|
|
5 // PG5 pin: 53
|
|
};
|
|
|
|
#if ! defined(EI_NOTEXTERNAL) && ! defined(EI_NOTINT0) && ! defined(EI_NOTINT1) && ! defined(EI_NOTINT2) && ! defined(EI_NOTINT3) && ! defined(EI_NOTINT4) && ! defined(EI_NOTINT5) && ! defined(EI_NOTINT6) && ! defined(EI_NOTINT7)
|
|
interruptFunctionType functionPointerArrayEXTERNAL[8];
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTB
|
|
struct functionPointersPortB {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
interruptFunctionType pinFour;
|
|
interruptFunctionType pinFive;
|
|
interruptFunctionType pinSix;
|
|
interruptFunctionType pinSeven;
|
|
};
|
|
typedef struct functionPointersPortB functionPointersPortB;
|
|
|
|
functionPointersPortB portBFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
#endif
|
|
|
|
#endif // ifndef NEEDFORSPEED
|
|
|
|
// For Pin Change Interrupts; since we're duplicating FALLING and RISING in software,
|
|
// we have to know how we were defined.
|
|
#ifndef EI_NOTPORTB
|
|
volatile uint8_t risingPinsPORTB=0;
|
|
volatile uint8_t fallingPinsPORTB=0;
|
|
static volatile uint8_t portSnapshotB;
|
|
#endif
|
|
|
|
#define PORTB_VECT PCINT0_vect
|
|
/*}}}*/
|
|
|
|
/* LEONARDO ***************************************************************************/
|
|
/* LEONARDO ***************************************************************************/
|
|
/* LEONARDO ***************************************************************************/
|
|
#elif defined __AVR_ATmega32U4__ || defined __AVR_ATmega16U4__
|
|
#define ARDUINO_LEONARDO /*{{{*/
|
|
#define EI_NOTPORTA
|
|
#define EI_NOTPORTC
|
|
#define EI_NOTPORTD
|
|
#define EI_NOTPORTJ
|
|
#define EI_NOTPORTK
|
|
/*}}}*/
|
|
|
|
#if defined EI_NOTPINCHANGE/*{{{*/
|
|
#ifndef EI_NOTPORTB
|
|
#define EI_NOTPORTB
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef NEEDFORSPEED
|
|
#define ARDUINO_PIN_B0 17
|
|
#define ARDUINO_PIN_B1 15
|
|
#define ARDUINO_PIN_B2 16
|
|
#define ARDUINO_PIN_B3 14
|
|
#define ARDUINO_PIN_B4 8
|
|
#define ARDUINO_PIN_B5 9
|
|
#define ARDUINO_PIN_B6 10
|
|
#define ARDUINO_PIN_B7 11
|
|
#define ARDUINO_PIN_D0 3
|
|
#define ARDUINO_PIN_D1 2
|
|
#define ARDUINO_PIN_D2 0
|
|
#define ARDUINO_PIN_D3 1
|
|
#define ARDUINO_PIN_E6 7
|
|
|
|
/* To derive this list:
|
|
sed -n -e '1,/digital_pin_to_port_PGM/d' -e '/^}/,$d' -e '/P/p' \
|
|
/usr/share/arduino/hardware/arduino/variants/leonardo/pins_arduino.h | \
|
|
awk '{print " ", $5 ", // " $5 " pin: " $3}'
|
|
...then massage the output as necessary to create the below:
|
|
*/
|
|
|
|
const uint8_t PROGMEM digital_pin_to_port_bit_number_PGM[] = {
|
|
2, // PD2 pin: D0
|
|
3, // PD3 pin: D1
|
|
1, // PD1 pin: D2
|
|
0, // PD0 pin: D3
|
|
4, // PD4 pin: D4
|
|
6, // PC6 pin: D5
|
|
7, // PD7 pin: D6
|
|
6, // PE6 pin: D7
|
|
4, // PB4 pin: D8 // we really only care about Port B, but I don't know that
|
|
5, // PB5 pin: D9 // shortening this array and doing array index arithmetic
|
|
6, // PB6 pin: D10 // would make the code any shorter.
|
|
7, // PB7 pin: D11
|
|
6, // PD6 pin: D12
|
|
7, // PC7 pin: D13
|
|
3, // PB3 pin: D14 MISO
|
|
1, // PB1 pin: D15 SCK
|
|
2, // PB2 pin: D16 MOSI
|
|
0 // PB0 pin: D17 SS (RXLED). Available on non-Leonardo 32u4 boards, at least (exposed on the Leonardo??)
|
|
// There are no ports we care about after pin 17.
|
|
};
|
|
|
|
|
|
#if ! defined(EI_NOTEXTERNAL) && ! defined(EI_NOTINT0) && ! defined(EI_NOTINT1) && ! defined(EI_NOTINT2) && ! defined(EI_NOTINT3) && ! defined(EI_NOTINT6)
|
|
interruptFunctionType functionPointerArrayEXTERNAL[5];
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTB
|
|
struct functionPointersPortB {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
interruptFunctionType pinFour;
|
|
interruptFunctionType pinFive;
|
|
interruptFunctionType pinSix;
|
|
interruptFunctionType pinSeven;
|
|
};
|
|
typedef struct functionPointersPortB functionPointersPortB;
|
|
|
|
functionPointersPortB portBFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
|
|
#endif
|
|
#endif // NEEDFOR SPEED
|
|
|
|
#ifndef EI_NOTPORTB
|
|
// For Pin Change Interrupts; since we're duplicating FALLING and RISING in software,
|
|
// we have to know how we were defined.
|
|
volatile uint8_t risingPinsPORTB=0;
|
|
volatile uint8_t fallingPinsPORTB=0;
|
|
|
|
// for the saved state of the ports
|
|
static volatile uint8_t portSnapshotB;
|
|
#endif
|
|
#define PORTB_VECT PCINT0_vect
|
|
/*}}}*/
|
|
|
|
/* 644/1284 ***************************************************************************/
|
|
/* 644/1284 ***************************************************************************/
|
|
/* 644/1284 ***************************************************************************/
|
|
#elif defined __AVR_ATmega1284P__ || defined __AVR_ATmega1284__ || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
|
|
#define MIGHTY1284 /*{{{*/
|
|
#define EI_NOTPORTJ
|
|
#define EI_NOTPORTK /*}}}*/
|
|
|
|
#if defined EI_NOTPINCHANGE/*{{{*/
|
|
#ifndef EI_NOTPORTA
|
|
#define EI_NOTPORTA
|
|
#endif
|
|
#ifndef EI_NOTPORTB
|
|
#define EI_NOTPORTB
|
|
#endif
|
|
#ifndef EI_NOTPORTC
|
|
#define EI_NOTPORTC
|
|
#endif
|
|
#ifndef EI_NOTPORTD
|
|
#define EI_NOTPORTD
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef INPUT_PULLUP
|
|
#define INPUT_PULLUP 0x2
|
|
#endif
|
|
|
|
#ifndef NEEDFORSPEED
|
|
#if defined BOBUINO_PINOUT
|
|
#define ARDUINO_PIN_A0 21
|
|
#define ARDUINO_PIN_A1 20
|
|
#define ARDUINO_PIN_A2 19
|
|
#define ARDUINO_PIN_A3 18
|
|
#define ARDUINO_PIN_A4 17
|
|
#define ARDUINO_PIN_A5 16
|
|
#define ARDUINO_PIN_A6 15
|
|
#define ARDUINO_PIN_A7 14
|
|
#define ARDUINO_PIN_B0 4
|
|
#define ARDUINO_PIN_B1 5
|
|
#define ARDUINO_PIN_B2 6 // INT2
|
|
#define ARDUINO_PIN_B3 7
|
|
#define ARDUINO_PIN_B4 10
|
|
#define ARDUINO_PIN_B5 11
|
|
#define ARDUINO_PIN_B6 12
|
|
#define ARDUINO_PIN_B7 13
|
|
#define ARDUINO_PIN_C0 22
|
|
#define ARDUINO_PIN_C1 23
|
|
#define ARDUINO_PIN_C2 24
|
|
#define ARDUINO_PIN_C3 25
|
|
#define ARDUINO_PIN_C4 26
|
|
#define ARDUINO_PIN_C5 27
|
|
#define ARDUINO_PIN_C6 28
|
|
#define ARDUINO_PIN_C7 29
|
|
#define ARDUINO_PIN_D0 0
|
|
#define ARDUINO_PIN_D1 1
|
|
#define ARDUINO_PIN_D2 2 // INT0
|
|
#define ARDUINO_PIN_D3 3 // INT1
|
|
#define ARDUINO_PIN_D4 30
|
|
#define ARDUINO_PIN_D5 8
|
|
#define ARDUINO_PIN_D6 9
|
|
#define ARDUINO_PIN_D7 31
|
|
|
|
const uint8_t PROGMEM digital_pin_to_port_bit_number_PGM[] = {
|
|
0, // PD0
|
|
1, // PD1
|
|
2, // PD2
|
|
3, // PD3
|
|
0, // PB0
|
|
1, // PB1
|
|
2, // PB2
|
|
3, // PB3
|
|
5, // PD5
|
|
6, // PD6
|
|
|
|
4, // PB4
|
|
5, // PB5
|
|
6, // PB6
|
|
7, // PB7
|
|
7, // PA7
|
|
6, // PA6
|
|
5, // PA5
|
|
4, // PA4
|
|
3, // PA3
|
|
2, // PA2
|
|
|
|
1, // PA1
|
|
0, // PA0
|
|
0, // PC0
|
|
1, // PC1
|
|
2, // PC2
|
|
3, // PC3
|
|
4, // PC4
|
|
5, // PC5
|
|
6, // PC6
|
|
7, // PC7
|
|
|
|
4, // PD4
|
|
7, // PD7
|
|
};
|
|
|
|
#else
|
|
#define ARDUINO_PIN_A0 24
|
|
#define ARDUINO_PIN_A1 25
|
|
#define ARDUINO_PIN_A2 26
|
|
#define ARDUINO_PIN_A3 27
|
|
#define ARDUINO_PIN_A4 28
|
|
#define ARDUINO_PIN_A5 29
|
|
#define ARDUINO_PIN_A6 30
|
|
#define ARDUINO_PIN_A7 31
|
|
#define ARDUINO_PIN_C0 16
|
|
#define ARDUINO_PIN_C1 17
|
|
#define ARDUINO_PIN_C2 18
|
|
#define ARDUINO_PIN_C3 19
|
|
#define ARDUINO_PIN_C4 20
|
|
#define ARDUINO_PIN_C5 21
|
|
#define ARDUINO_PIN_C6 22
|
|
#define ARDUINO_PIN_C7 23
|
|
|
|
// For boards with the 44 pin options: vectors B & D are reversed
|
|
// Thanks to Sara Damiano for these updates!!!
|
|
#if defined ARDUINO_AVR_ENVIRODIY_MAYFLY || defined ARDUINO_AVR_SODAQ_MBILI
|
|
#define ARDUINO_PIN_B0 8
|
|
#define ARDUINO_PIN_B1 9
|
|
#define ARDUINO_PIN_B2 10 // INT2
|
|
#define ARDUINO_PIN_B3 11
|
|
#define ARDUINO_PIN_B4 12
|
|
#define ARDUINO_PIN_B5 13
|
|
#define ARDUINO_PIN_B6 14
|
|
#define ARDUINO_PIN_B7 15
|
|
#define ARDUINO_PIN_D0 0
|
|
#define ARDUINO_PIN_D1 1
|
|
#define ARDUINO_PIN_D2 2 // INT0
|
|
#define ARDUINO_PIN_D3 3 // INT1
|
|
#define ARDUINO_PIN_D4 4
|
|
#define ARDUINO_PIN_D5 5
|
|
#define ARDUINO_PIN_D6 6
|
|
#define ARDUINO_PIN_D7 7
|
|
#else
|
|
#define ARDUINO_PIN_B0 0
|
|
#define ARDUINO_PIN_B1 1
|
|
#define ARDUINO_PIN_B2 2 // INT2
|
|
#define ARDUINO_PIN_B3 3
|
|
#define ARDUINO_PIN_B4 4
|
|
#define ARDUINO_PIN_B5 5
|
|
#define ARDUINO_PIN_B6 6
|
|
#define ARDUINO_PIN_B7 7
|
|
#define ARDUINO_PIN_D0 8
|
|
#define ARDUINO_PIN_D1 9
|
|
#define ARDUINO_PIN_D2 10 // INT0
|
|
#define ARDUINO_PIN_D3 11 // INT1
|
|
#define ARDUINO_PIN_D4 12
|
|
#define ARDUINO_PIN_D5 13
|
|
#define ARDUINO_PIN_D6 14
|
|
#define ARDUINO_PIN_D7 15
|
|
#endif
|
|
|
|
const uint8_t PROGMEM digital_pin_to_port_bit_number_PGM[] = {
|
|
0, // 0 == port B, 0
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
0, // 8 == port D, 0
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
0, // 16 == port C, 0
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
0, // 24 == port A, 0
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7
|
|
};
|
|
#endif
|
|
|
|
|
|
#if ! defined(EI_NOTEXTERNAL) && ! defined(EI_NOTINT0) && ! defined(EI_NOTINT1) && ! defined(EI_NOTINT2)
|
|
interruptFunctionType functionPointerArrayEXTERNAL[3];
|
|
#endif
|
|
|
|
struct functionPointers {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
interruptFunctionType pinFour;
|
|
interruptFunctionType pinFive;
|
|
interruptFunctionType pinSix;
|
|
interruptFunctionType pinSeven;
|
|
};
|
|
|
|
#ifndef EI_NOTPORTA
|
|
typedef struct functionPointers functionPointersPortA;
|
|
functionPointers portAFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTB
|
|
typedef struct functionPointers functionPointersPortB;
|
|
functionPointersPortB portBFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTC
|
|
typedef struct functionPointers functionPointersPortC;
|
|
functionPointersPortC portCFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTD
|
|
typedef struct functionPointers functionPointersPortD;
|
|
functionPointersPortD portDFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
#endif
|
|
#endif // NEEDFORSPEED
|
|
|
|
#ifndef EI_NOTPORTA
|
|
volatile uint8_t risingPinsPORTA=0;
|
|
volatile uint8_t fallingPinsPORTA=0;
|
|
// for the saved state of the ports
|
|
static volatile uint8_t portSnapshotA;
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTB
|
|
volatile uint8_t risingPinsPORTB=0;
|
|
volatile uint8_t fallingPinsPORTB=0;
|
|
static volatile uint8_t portSnapshotB;
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTC
|
|
volatile uint8_t risingPinsPORTC=0;
|
|
volatile uint8_t fallingPinsPORTC=0;
|
|
static volatile uint8_t portSnapshotC;
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTD
|
|
volatile uint8_t risingPinsPORTD=0;
|
|
volatile uint8_t fallingPinsPORTD=0;
|
|
static volatile uint8_t portSnapshotD;
|
|
#endif
|
|
|
|
// the vectors (eg, "PCINT0_vect") are defined in the avr.h files, like iom1284p.h
|
|
#define PORTA_VECT PCINT0_vect
|
|
#define PORTB_VECT PCINT1_vect
|
|
#define PORTC_VECT PCINT2_vect
|
|
#define PORTD_VECT PCINT3_vect
|
|
/*}}}*/
|
|
|
|
/* 24/44/84 ***************************************************************************/
|
|
/* 24/44/84 ***************************************************************************/
|
|
/* 24/44/84 ***************************************************************************/
|
|
#elif defined __AVR_ATtiny24__ || defined __AVR_ATtiny24A__ || defined __AVR_ATtiny44__ || defined __AVR_ATtiny44A__ || defined __AVR_ATtiny84__ || defined __AVR_ATtiny84A_
|
|
#define EI_ATTINY24 /*{{{*/
|
|
#define EI_NOTPORTC
|
|
#define EI_NOTPORTD
|
|
#define EI_NOTPORTJ
|
|
#define EI_NOTPORTK
|
|
/*}}}*/
|
|
|
|
#define EI_NOTINT1
|
|
|
|
#if defined EI_NOTPINCHANGE/*{{{*/
|
|
#ifndef EI_NOTPORTA
|
|
#define EI_NOTPORTA
|
|
#endif
|
|
#ifndef EI_NOTPORTB
|
|
#define EI_NOTPORTB
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef INPUT_PULLUP
|
|
#define INPUT_PULLUP 0x2
|
|
#endif
|
|
|
|
#ifndef NEEDFORSPEED
|
|
|
|
#define ARDUINO_PIN_B3 11
|
|
#define ARDUINO_PIN_B2 8
|
|
#define ARDUINO_PIN_B1 9
|
|
#define ARDUINO_PIN_B0 10
|
|
#define ARDUINO_PIN_A0 0
|
|
#define ARDUINO_PIN_A1 1
|
|
#define ARDUINO_PIN_A2 2
|
|
#define ARDUINO_PIN_A3 3
|
|
#define ARDUINO_PIN_A4 4
|
|
#define ARDUINO_PIN_A5 5
|
|
#define ARDUINO_PIN_A6 6
|
|
#define ARDUINO_PIN_A7 7
|
|
|
|
const uint8_t PROGMEM digital_pin_to_port_bit_number_PGM[] = {
|
|
0, // pin 0 == port A, bit 0
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
2, // pin 8 = port B, bit 2
|
|
1,
|
|
0,
|
|
3
|
|
};
|
|
#if ! defined(EI_NOTEXTERNAL) && ! defined(EI_NOTINT0)
|
|
interruptFunctionType externalFunctionPointer=0;
|
|
#endif
|
|
|
|
// For Pin Change Interrupts; since we're duplicating FALLING and RISING in software,
|
|
// we have to know how the ports were defined.
|
|
#ifndef EI_NOTPORTA
|
|
struct functionPointersPortA {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
interruptFunctionType pinFour;
|
|
interruptFunctionType pinFive;
|
|
interruptFunctionType pinSix;
|
|
interruptFunctionType pinSeven;
|
|
};
|
|
typedef struct functionPointersPortA functionPointersPortA;
|
|
|
|
functionPointersPortA portAFunctions = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
|
|
#endif // ifndef EI_NOTPORTA
|
|
#ifndef EI_NOTPORTB
|
|
struct functionPointersPortB {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
};
|
|
typedef struct functionPointersPortB functionPointersPortB;
|
|
|
|
functionPointersPortB portBFunctions = { NULL, NULL, NULL, NULL };
|
|
#endif // ifndef EI_NOTPORTB
|
|
#endif // NEEDFORSPEED
|
|
|
|
// For Pin Change Interrupts; since we're duplicating FALLING and RISING in software,
|
|
// we have to know how we were defined.
|
|
#ifndef EI_NOTPORTA
|
|
volatile uint8_t risingPinsPORTA=0;
|
|
volatile uint8_t fallingPinsPORTA=0;
|
|
// for the saved state of the ports
|
|
static volatile uint8_t portSnapshotA;
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTB
|
|
volatile uint8_t risingPinsPORTB=0;
|
|
volatile uint8_t fallingPinsPORTB=0;
|
|
// for the saved state of the ports
|
|
static volatile uint8_t portSnapshotB;
|
|
#endif
|
|
|
|
#define PORTA_VECT PCINT0_vect
|
|
#define PORTB_VECT PCINT1_vect/*}}}*/
|
|
|
|
/* 25/45/85 ***************************************************************************/
|
|
/* 25/45/85 ***************************************************************************/
|
|
/* 25/45/85 ***************************************************************************/
|
|
#elif defined __AVR_ATtiny25__ || defined __AVR_ATtiny45__ || defined __AVR_ATtiny85__
|
|
#define EI_ATTINY25 /*{{{*/
|
|
#define EI_NOTPORTA
|
|
#define EI_NOTPORTC
|
|
#define EI_NOTPORTD
|
|
#define EI_NOTPORTJ
|
|
#define EI_NOTPORTK
|
|
/*}}}*/
|
|
|
|
#if defined EI_NOTPINCHANGE/*{{{*/
|
|
#ifndef EI_NOTPORTB
|
|
#define EI_NOTPORTB
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef INPUT_PULLUP
|
|
#define INPUT_PULLUP 0x2
|
|
#endif
|
|
|
|
#ifndef NEEDFORSPEED
|
|
|
|
#define ARDUINO_PIN_B0 0
|
|
#define ARDUINO_PIN_B1 1
|
|
#define ARDUINO_PIN_B2 2
|
|
#define ARDUINO_PIN_B3 3
|
|
#define ARDUINO_PIN_B4 4
|
|
#define ARDUINO_PIN_B5 5
|
|
|
|
const uint8_t PROGMEM digital_pin_to_port_bit_number_PGM[] = {
|
|
0, // pin 0 == port B, bit 0
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5
|
|
};
|
|
#if ! defined(EI_NOTEXTERNAL) && ! defined(EI_NOTINT0)
|
|
interruptFunctionType externalFunctionPointer=0;
|
|
#endif
|
|
|
|
#ifndef EI_NOTPORTB
|
|
struct functionPointersPortB {
|
|
interruptFunctionType pinZero;
|
|
interruptFunctionType pinOne;
|
|
interruptFunctionType pinTwo;
|
|
interruptFunctionType pinThree;
|
|
interruptFunctionType pinFour;
|
|
interruptFunctionType pinFive;
|
|
};
|
|
typedef struct functionPointersPortB functionPointersPortB;
|
|
|
|
functionPointersPortB portBFunctions = { NULL, NULL, NULL, NULL, NULL, NULL };
|
|
|
|
#endif // ifndef EI_NOTPORTB
|
|
#endif // NEEDFORSPEED
|
|
|
|
#ifndef EI_NOTPORTB
|
|
// the vectors (eg, "PCINT0_vect") are defined in the avr.h files, like iom1284p.h
|
|
// For Pin Change Interrupts; since we're duplicating FALLING and RISING in software,
|
|
// we have to know how the ports were defined.
|
|
volatile uint8_t risingPinsPORTB=0;
|
|
volatile uint8_t fallingPinsPORTB=0;
|
|
// for the saved state of the ports
|
|
static volatile uint8_t portSnapshotB;
|
|
#endif
|
|
|
|
#define PORTB_VECT PCINT0_vect/*}}}*/
|
|
|
|
#endif // #if defined __AVR_ATmega168__ || defined __AVR_ATmega168A__ ... (etc.) ...
|
|
|
|
// ===========================================================================================
|
|
// END END END DATA STRUCTURES ===============================================================
|
|
// ===========================================================================================
|
|
|
|
// From /usr/share/arduino/hardware/arduino/cores/robot/Arduino.h
|
|
// #define CHANGE 1
|
|
// #define FALLING 2
|
|
// #define RISING 3
|
|
|
|
#if !(defined EI_ATTINY24) && !(defined EI_ATTINY25)
|
|
// Example: EI_printPSTR("This is a nice long string that takes no static ram");
|
|
#define EI_printPSTR(x) EI_SerialPrint_P(PSTR(x))
|
|
void EI_SerialPrint_P(const char *str) {
|
|
for (uint8_t c; (c = pgm_read_byte(str)); str++) Serial.write(c);
|
|
}
|
|
#endif
|
|
|
|
|
|
// ===========================================================================================
|
|
// ===========================================================================================
|
|
// enableInterrupt(interrupDesignator, userFunction, mode); ==================================
|
|
// ===========================================================================================
|
|
// ===========================================================================================
|
|
|
|
// "interruptDesignator" is simply the Arduino pin optionally OR'ed with
|
|
// PINCHANGEINTERRUPT (== 0x80)
|
|
void enableInterrupt(uint8_t interruptDesignator, interruptFunctionType userFunction, uint8_t mode) {
|
|
uint8_t arduinoPin;
|
|
uint8_t portNumber=0;
|
|
uint8_t portMask=0;
|
|
#ifndef NEEDFORSPEED
|
|
uint8_t portBitNumber; // when an interrupted pin is found, this will be used to choose the function.
|
|
interruptFunctionType *calculatedPointer;
|
|
#endif
|
|
|
|
arduinoPin=interruptDesignator & ~PINCHANGEINTERRUPT;
|
|
|
|
// *************************************************************************************
|
|
// Pin Change Interrupts
|
|
// *************************************************************************************
|
|
|
|
/*{{{*/
|
|
#if defined ARDUINO_328
|
|
if ( (interruptDesignator & PINCHANGEINTERRUPT) || (arduinoPin != 2 && arduinoPin != 3) ) {
|
|
#elif defined MIGHTY1284
|
|
if ( (interruptDesignator & PINCHANGEINTERRUPT) ||
|
|
(arduinoPin != ARDUINO_PIN_B2 && arduinoPin != ARDUINO_PIN_D2 && arduinoPin != ARDUINO_PIN_D3) ) {
|
|
#elif defined ARDUINO_LEONARDO
|
|
if ( (arduinoPin > 3) && (arduinoPin != 7) ) {
|
|
#elif defined EI_ATTINY24
|
|
if ( (interruptDesignator & PINCHANGEINTERRUPT) || (arduinoPin != 8) ) {
|
|
#elif defined EI_ATTINY25
|
|
if ( (interruptDesignator & PINCHANGEINTERRUPT) || (arduinoPin != 2) ) {
|
|
#endif
|
|
#if defined ARDUINO_328 || defined MIGHTY1284 || defined ARDUINO_LEONARDO
|
|
portMask=pgm_read_byte(&digital_pin_to_bit_mask_PGM[arduinoPin]);
|
|
portNumber=pgm_read_byte(&digital_pin_to_port_PGM[arduinoPin]);
|
|
#elif defined EI_ATTINY25
|
|
portMask=pgm_read_byte(&digital_pin_to_bit_mask_PGM[arduinoPin]);
|
|
portNumber=PB;
|
|
#elif defined EI_ATTINY24
|
|
// This is not a true Arduino pin... it's pin 4 on the chip, which is RESET.
|
|
// I could imagine that one would want to use that pin for something other than RESET.
|
|
if (arduinoPin == 11) {
|
|
portMask=_BV(3);
|
|
portNumber=PB;
|
|
} else {
|
|
portMask=pgm_read_byte(&digital_pin_to_bit_mask_PGM[arduinoPin]);
|
|
portNumber=pgm_read_byte(&digital_pin_to_port_PGM[arduinoPin]);
|
|
}
|
|
#elif defined ARDUINO_MEGA
|
|
#if defined __AVR_ATmega640__ || defined __AVR_ATmega2560__ || defined __AVR_ATmega1280__
|
|
// NOTE: PJ2-6 and PE6 & 7 are not exposed on the Arduino, but they are supported here
|
|
// for software interrupts and support of non-Arduino platforms which expose more pins.
|
|
// PJ2-6 are called pins 70-74, PE6 is pin 75, PE7 is pin 76.
|
|
if ( (arduinoPin != 2 && arduinoPin != 3 && arduinoPin != 75 && arduinoPin != 76
|
|
&& (arduinoPin < 18 || arduinoPin > 21))
|
|
) {
|
|
if (arduinoPin > 69) { // Dastardly tricks to support PortJ 2-7
|
|
portMask=pgm_read_byte(&digital_pin_to_bit_mask_PGM[arduinoPin-6]); // Steal from PK
|
|
portNumber=PJ;
|
|
} else {
|
|
portMask=pgm_read_byte(&digital_pin_to_bit_mask_PGM[arduinoPin]);
|
|
portNumber=pgm_read_byte(&digital_pin_to_port_PGM[arduinoPin]);
|
|
}
|
|
#elif defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
|
|
if (!(((arduinoPin >= 4) && (arduinoPin <= 7)) || ((arduinoPin >= 18) && (arduinoPin <=21)))) {
|
|
portMask=pgm_read_byte(&digital_pin_to_bit_mask_PGM[arduinoPin]);
|
|
portNumber=pgm_read_byte(&digital_pin_to_port_PGM[arduinoPin]);
|
|
#endif
|
|
#else
|
|
#error Unsupported Arduino platform
|
|
#endif
|
|
|
|
// *************************************************************************************
|
|
// Store the rising/falling pins
|
|
// *************************************************************************************
|
|
|
|
if ((mode == RISING) || (mode == CHANGE)) {
|
|
#define EI_SECTION_RISING
|
|
|
|
#if defined MIGHTY1284
|
|
#include "utility/ei_PinChange1284.h"
|
|
#elif defined ARDUINO_328
|
|
#include "utility/ei_PinChange328.h"
|
|
#elif defined ARDUINO_MEGA
|
|
#include "utility/ei_PinChange2560.h"
|
|
#elif defined ARDUINO_LEONARDO
|
|
#include "utility/ei_PinChangeLeonardo.h"
|
|
#elif defined EI_ATTINY24
|
|
#include "utility/ei_PinChangeTiny24.h"
|
|
#elif defined EI_ATTINY25
|
|
#include "utility/ei_PinChangeTiny25.h"
|
|
#endif
|
|
#undef EI_SECTION_RISING
|
|
}
|
|
|
|
if ((mode == FALLING) || (mode == CHANGE)) {
|
|
#define EI_SECTION_FALLING
|
|
#if defined MIGHTY1284
|
|
#include "utility/ei_PinChange1284.h"
|
|
#elif defined ARDUINO_328
|
|
#include "utility/ei_PinChange328.h"
|
|
#elif defined ARDUINO_MEGA
|
|
#include "utility/ei_PinChange2560.h"
|
|
#elif defined ARDUINO_LEONARDO
|
|
#include "utility/ei_PinChangeLeonardo.h"
|
|
#elif defined EI_ATTINY24
|
|
#include "utility/ei_PinChangeTiny24.h"
|
|
#elif defined EI_ATTINY25
|
|
#include "utility/ei_PinChangeTiny25.h"
|
|
#endif
|
|
#undef EI_SECTION_FALLING
|
|
}
|
|
|
|
#ifndef NEEDFORSPEED
|
|
// When an interrupted pin is found, this will be used to choose the function.
|
|
// This is used in the utility/<#included files>, below.
|
|
portBitNumber=pgm_read_byte(&digital_pin_to_port_bit_number_PGM[arduinoPin]);
|
|
#endif
|
|
|
|
// *************************************************************************************
|
|
// assign the function to be run in the ISR
|
|
// save the initial value of the port
|
|
// initialize interrupt registers PCMSKx and PCICR
|
|
// *************************************************************************************
|
|
|
|
#define EI_SECTION_ASSIGNFUNCTIONSREGISTERS
|
|
#if defined MIGHTY1284
|
|
#include "utility/ei_PinChange1284.h"
|
|
#elif defined ARDUINO_328
|
|
#include "utility/ei_PinChange328.h"
|
|
#elif defined ARDUINO_MEGA
|
|
#include "utility/ei_PinChange2560.h"
|
|
#elif defined ARDUINO_LEONARDO
|
|
#include "utility/ei_PinChangeLeonardo.h"
|
|
#elif defined EI_ATTINY24
|
|
#include "utility/ei_PinChangeTiny24.h"
|
|
#elif defined EI_ATTINY25
|
|
#include "utility/ei_PinChangeTiny25.h"
|
|
#endif
|
|
#undef EI_SECTION_ASSIGNFUNCTIONSREGISTERS
|
|
|
|
*pcmsk |= portMask; // appropriate PCMSKn bit is set, e.g. this could be PCMSK1 |= portMask;
|
|
|
|
// With the exception of the Global Interrupt Enable bit in SREG, interrupts on the arduinoPin
|
|
// are now ready. GIE may have already been set on a previous enable, so it's important
|
|
// to take note of the order in which things were done, above./*}}}*/
|
|
|
|
// *************************************************************************************
|
|
// External Interrupts
|
|
// *************************************************************************************
|
|
|
|
} else {/*{{{*/
|
|
#ifndef EI_NOTEXTERNAL
|
|
uint8_t origSREG; // to save for interrupts
|
|
origSREG = SREG;
|
|
cli(); // no interrupts while we're setting up an interrupt.
|
|
|
|
#define EI_SECTION_ENABLEEXTERNAL
|
|
#if defined MIGHTY1284
|
|
#include "utility/ei_External1284.h"
|
|
#elif defined ARDUINO_328
|
|
#include "utility/ei_External328.h"
|
|
#elif defined ARDUINO_MEGA
|
|
#include "utility/ei_External2560.h"
|
|
#elif defined ARDUINO_LEONARDO
|
|
#include "utility/ei_ExternalLeonardo.h"
|
|
#elif defined EI_ATTINY24
|
|
#include "utility/ei_ExternalTiny24.h"
|
|
#elif defined EI_ATTINY25
|
|
#include "utility/ei_ExternalTiny25.h"
|
|
#endif
|
|
#undef EI_SECTION_ENABLEEXTERNAL
|
|
|
|
SREG=origSREG;
|
|
#endif
|
|
}
|
|
}
|
|
/*}}}*/
|
|
|
|
// ===========================================================================================
|
|
// ===========================================================================================
|
|
// disableInterrupt(interrupDesignator); =====================================================
|
|
// ===========================================================================================
|
|
// ===========================================================================================
|
|
void disableInterrupt (uint8_t interruptDesignator) {
|
|
|
|
uint8_t origSREG; // to save for interrupts
|
|
uint8_t arduinoPin;
|
|
uint8_t portMask=0;
|
|
#if ! (defined EI_ATTINY25)
|
|
uint8_t portNumber=0;
|
|
#endif
|
|
|
|
origSREG = SREG;
|
|
cli();
|
|
arduinoPin=interruptDesignator & ~PINCHANGEINTERRUPT;
|
|
|
|
/*{{{*/
|
|
#if defined ARDUINO_328
|
|
if ( (interruptDesignator & PINCHANGEINTERRUPT) || (arduinoPin != 2 && arduinoPin != 3) ) {
|
|
#elif defined MIGHTY1284
|
|
if ( (interruptDesignator & PINCHANGEINTERRUPT) ||
|
|
(arduinoPin != ARDUINO_PIN_B2 && arduinoPin != ARDUINO_PIN_D2 && arduinoPin != ARDUINO_PIN_D3) ) {
|
|
#elif defined EI_ATTINY24
|
|
if ( (interruptDesignator & PINCHANGEINTERRUPT) || (arduinoPin != 8) ) {
|
|
#elif defined EI_ATTINY25
|
|
if ( (interruptDesignator & PINCHANGEINTERRUPT) || (arduinoPin != 2) ) {
|
|
#elif defined ARDUINO_LEONARDO
|
|
if ( (arduinoPin > 3) && (arduinoPin != 7) ) {
|
|
#endif
|
|
#if defined ARDUINO_328 || defined MIGHTY1284 || defined ARDUINO_LEONARDO
|
|
portMask=pgm_read_byte(&digital_pin_to_bit_mask_PGM[arduinoPin]);
|
|
portNumber=pgm_read_byte(&digital_pin_to_port_PGM[arduinoPin]);
|
|
#elif defined EI_ATTINY24
|
|
// This is not a true Arduino pin... it's pin 4 on the chip, which is RESET.
|
|
// I could imagine that one would want to use that pin for something other than RESET.
|
|
if (arduinoPin == 11) {
|
|
portMask=_BV(3);
|
|
portNumber=PB;
|
|
} else {
|
|
portMask=pgm_read_byte(&digital_pin_to_bit_mask_PGM[arduinoPin]);
|
|
portNumber=pgm_read_byte(&digital_pin_to_port_PGM[arduinoPin]);
|
|
}
|
|
#elif defined EI_ATTINY25
|
|
portMask=pgm_read_byte(&digital_pin_to_bit_mask_PGM[arduinoPin]);
|
|
#elif defined ARDUINO_MEGA
|
|
// NOTE: PJ2-6 and PE6 & 7 are not exposed on the Arduino, but they are supported here
|
|
// for software interrupts and support of non-Arduino platforms which expose more pins.
|
|
// PJ2-6 are called pins 70-74, PE6 is pin 75, PE7 is pin 76.
|
|
if ( (arduinoPin != 2 && arduinoPin != 3 && arduinoPin != 75 && arduinoPin != 76
|
|
&& (arduinoPin < 18 || arduinoPin > 21))
|
|
) {
|
|
if (arduinoPin > 69) { // Dastardly tricks to support PortJ 2-7
|
|
portMask=pgm_read_byte(&digital_pin_to_bit_mask_PGM[arduinoPin-6]); // Steal from PK
|
|
portNumber=PJ;
|
|
} else {
|
|
portMask=pgm_read_byte(&digital_pin_to_bit_mask_PGM[arduinoPin]);
|
|
portNumber=pgm_read_byte(&digital_pin_to_port_PGM[arduinoPin]);
|
|
}
|
|
#else
|
|
#error Unsupported Arduino platform
|
|
#endif
|
|
|
|
#define EI_SECTION_DISABLEPINCHANGE
|
|
#if defined MIGHTY1284
|
|
#include "utility/ei_PinChange1284.h"
|
|
#elif defined ARDUINO_328
|
|
#include "utility/ei_PinChange328.h"
|
|
#elif defined ARDUINO_MEGA
|
|
#include "utility/ei_PinChange2560.h"
|
|
#elif defined LEONARDO
|
|
#include "utility/ei_PinChangeLeonardo.h"
|
|
#elif defined EI_ATTINY24
|
|
#include "utility/ei_PinChangeTiny24.h"
|
|
#elif defined EI_ATTINY25
|
|
#include "utility/ei_PinChangeTiny25.h"
|
|
#endif
|
|
#undef EI_SECTION_DISABLEPINCHANGE
|
|
} else {
|
|
#ifndef EI_NOTEXTERNAL
|
|
#define EI_SECTION_DISABLEEXTERNAL
|
|
#if defined MIGHTY1284
|
|
#include "utility/ei_External1284.h"
|
|
#elif defined ARDUINO_328
|
|
#include "utility/ei_External328.h"
|
|
#elif defined ARDUINO_MEGA
|
|
#include "utility/ei_External2560.h"
|
|
#elif defined ARDUINO_LEONARDO
|
|
#include "utility/ei_ExternalLeonardo.h"
|
|
#elif defined ATTINY24
|
|
#include "utility/ei_ExternalTiny24.h"
|
|
#elif defined EI_ATTINY25
|
|
#include "utility/ei_ExternalTiny25.h"
|
|
#endif
|
|
#undef EI_SECTION_DISABLEEXTERNAL
|
|
#endif
|
|
}
|
|
SREG = origSREG;/*}}}*/
|
|
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////// ISRs /////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// *************************************************************************************
|
|
// External Interrupts
|
|
// *************************************************************************************
|
|
#ifndef EI_NOTEXTERNAL
|
|
#ifndef EI_NOTINT0
|
|
ISR(INT0_vect) {/*{{{*/
|
|
#ifndef NEEDFORSPEED
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
#if defined MIGHTY1284
|
|
arduinoInterruptedPin=ARDUINO_PIN_D2; arduinoPinState=PIND & _BV(2);
|
|
#elif defined ARDUINO_MEGA
|
|
arduinoInterruptedPin=ARDUINO_PIN_D0; arduinoPinState=PIND & _BV(0);
|
|
#elif defined ARDUINO_LEONARDO
|
|
arduinoInterruptedPin=ARDUINO_PIN_D0; arduinoPinState=PIND & _BV(0);
|
|
#elif defined ARDUINO_328
|
|
arduinoInterruptedPin=ARDUINO_PIN_D2; arduinoPinState=PIND & _BV(2);
|
|
#elif defined EI_ATTINY24
|
|
arduinoInterruptedPin=ARDUINO_PIN_B2; arduinoPinState=PINB & _BV(2);
|
|
#elif defined EI_ATTINY25
|
|
arduinoInterruptedPin=ARDUINO_PIN_B0; arduinoPinState=PINB & _BV(0);
|
|
#endif
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
#if ! defined EI_ATTINY25 && ! defined EI_ATTINY24
|
|
(*functionPointerArrayEXTERNAL[0])();
|
|
#else
|
|
externalFunctionPointer();
|
|
#endif
|
|
#else
|
|
#if defined ARDUINO_AVR_ENVIRODIY_MAYFLY || defined ARDUINO_AVR_SODAQ_MBILI
|
|
INTERRUPT_FLAG_PIN2++;
|
|
#elif defined MIGHTY1284
|
|
INTERRUPT_FLAG_PIN10++;
|
|
#endif
|
|
#if defined ARDUINO_MEGA
|
|
#ifdef INTERRUPT_FLAG_PIN21
|
|
INTERRUPT_FLAG_PIN21++;
|
|
#endif
|
|
#endif
|
|
#if defined ARDUINO_LEONARDO
|
|
#ifdef INTERRUPT_FLAG_PIN3
|
|
INTERRUPT_FLAG_PIN3++;
|
|
#endif
|
|
#endif
|
|
#if defined ARDUINO_328
|
|
#ifdef INTERRUPT_FLAG_PIN2
|
|
INTERRUPT_FLAG_PIN2++;
|
|
#endif
|
|
#endif
|
|
|
|
#if defined EI_ATTINY24
|
|
#ifdef INTERRUPT_FLAG_PIN8
|
|
INTERRUPT_FLAG_PIN8++;
|
|
#endif
|
|
#endif
|
|
#if defined EI_ATTINY25
|
|
#ifdef INTERRUPT_FLAG_PIN2
|
|
INTERRUPT_FLAG_PIN2++;
|
|
#endif
|
|
#endif
|
|
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTINT0
|
|
|
|
#if ! defined(EI_ATTINY24) && ! defined(EI_ATTINY25)
|
|
#ifndef EI_NOTINT1
|
|
ISR(INT1_vect) {/*{{{*/
|
|
#ifndef NEEDFORSPEED
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
#if defined MIGHTY1284
|
|
arduinoInterruptedPin=ARDUINO_PIN_D3; arduinoPinState=PIND & _BV(3);
|
|
#elif defined ARDUINO_MEGA
|
|
arduinoInterruptedPin=ARDUINO_PIN_D1; arduinoPinState=PIND & _BV(1);
|
|
#elif defined ARDUINO_LEONARDO
|
|
arduinoInterruptedPin=ARDUINO_PIN_D1; arduinoPinState=PIND & _BV(1);
|
|
#elif defined ARDUINO_328
|
|
arduinoInterruptedPin=ARDUINO_PIN_D3; arduinoPinState=PIND & _BV(3);
|
|
#endif
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
(*functionPointerArrayEXTERNAL[1])();
|
|
#else
|
|
#if defined ARDUINO_AVR_ENVIRODIY_MAYFLY || defined ARDUINO_AVR_SODAQ_MBILI
|
|
INTERRUPT_FLAG_PIN3++;
|
|
#elif defined MIGHTY1284
|
|
INTERRUPT_FLAG_PIN11++;
|
|
#endif
|
|
#if defined ARDUINO_MEGA
|
|
#ifdef INTERRUPT_FLAG_PIN20
|
|
INTERRUPT_FLAG_PIN20++;
|
|
#endif
|
|
#endif
|
|
#if defined ARDUINO_LEONARDO
|
|
#ifdef INTERRUPT_FLAG_PIN2
|
|
INTERRUPT_FLAG_PIN2++;
|
|
#endif
|
|
#endif
|
|
#if defined ARDUINO_328
|
|
#ifdef INTERRUPT_FLAG_PIN3
|
|
INTERRUPT_FLAG_PIN3++;
|
|
#endif
|
|
#endif
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTINT1
|
|
#endif
|
|
|
|
#if defined ARDUINO_MEGA || defined ARDUINO_LEONARDO || defined MIGHTY1284
|
|
#ifndef EI_NOTINT2
|
|
ISR(INT2_vect) {/*{{{*/
|
|
#ifndef NEEDFORSPEED
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
#if defined MIGHTY1284
|
|
arduinoInterruptedPin=ARDUINO_PIN_B2; arduinoPinState=PINB & _BV(2);
|
|
#elif defined ARDUINO_MEGA
|
|
arduinoInterruptedPin=ARDUINO_PIN_D2; arduinoPinState=PIND & _BV(2);
|
|
#elif defined ARDUINO_LEONARDO
|
|
arduinoInterruptedPin=ARDUINO_PIN_D2; arduinoPinState=PIND & _BV(2);
|
|
#endif
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
(*functionPointerArrayEXTERNAL[2])();
|
|
#else
|
|
#if defined ARDUINO_AVR_ENVIRODIY_MAYFLY || defined ARDUINO_AVR_SODAQ_MBILI
|
|
INTERRUPT_FLAG_PIN10++;
|
|
#elif defined MIGHTY1284
|
|
INTERRUPT_FLAG_PIN2++;
|
|
#endif
|
|
#if defined ARDUINO_MEGA
|
|
#ifdef INTERRUPT_FLAG_PIN19
|
|
INTERRUPT_FLAG_PIN19++;
|
|
#endif
|
|
#else
|
|
#ifdef INTERRUPT_FLAG_PIN0
|
|
INTERRUPT_FLAG_PIN0++;
|
|
#endif
|
|
#endif
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTINT2
|
|
#endif // ARDUINO_MEGA || ARDUINO_LEONARDO || MIGHTY1284
|
|
|
|
#if defined ARDUINO_MEGA || defined ARDUINO_LEONARDO
|
|
#ifndef EI_NOTINT3
|
|
ISR(INT3_vect) {/*{{{*/
|
|
#ifndef NEEDFORSPEED
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
#if defined ARDUINO_MEGA
|
|
arduinoInterruptedPin=ARDUINO_PIN_D3; arduinoPinState=PIND & _BV(3);
|
|
#elif defined ARDUINO_LEONARDO
|
|
arduinoInterruptedPin=ARDUINO_PIN_D3; arduinoPinState=PIND & _BV(3);
|
|
#endif
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
(*functionPointerArrayEXTERNAL[3])();
|
|
#else
|
|
#if defined ARDUINO_MEGA
|
|
#ifdef INTERRUPT_FLAG_PIN18
|
|
INTERRUPT_FLAG_PIN18++;
|
|
#endif
|
|
#else
|
|
#ifdef INTERRUPT_FLAG_PIN1
|
|
INTERRUPT_FLAG_PIN1++;
|
|
#endif
|
|
#endif
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTINT3
|
|
#endif // ARDUINO_MEGA || ARDUINO_LEONARDO
|
|
|
|
#if defined ARDUINO_MEGA
|
|
#ifndef EI_NOTINT4
|
|
ISR(INT4_vect) {/*{{{*/
|
|
#ifndef NEEDFORSPEED
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
arduinoInterruptedPin=ARDUINO_PIN_E4; arduinoPinState=PINE & _BV(4);
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
(*functionPointerArrayEXTERNAL[4])();
|
|
#else
|
|
#ifdef INTERRUPT_FLAG_PIN2
|
|
INTERRUPT_FLAG_PIN2++;
|
|
#endif
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTINT4
|
|
|
|
#ifndef EI_NOTINT5
|
|
ISR(INT5_vect) {/*{{{*/
|
|
#ifndef NEEDFORSPEED
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
arduinoInterruptedPin=ARDUINO_PIN_E5; arduinoPinState=PINE & _BV(5);
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
(*functionPointerArrayEXTERNAL[5])();
|
|
#else
|
|
#ifdef INTERRUPT_FLAG_PIN3
|
|
INTERRUPT_FLAG_PIN3++;
|
|
#endif
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTINT5
|
|
|
|
#ifndef EI_NOTINT6
|
|
ISR(INT6_vect) {/*{{{*/
|
|
#ifndef NEEDFORSPEED
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
arduinoInterruptedPin=ARDUINO_PIN_E6; arduinoPinState=PINE & _BV(6);
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
(*functionPointerArrayEXTERNAL[6])();
|
|
#else
|
|
#ifdef INTERRUPT_FLAG_PIN75
|
|
INTERRUPT_FLAG_PIN75++;
|
|
#endif
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTINT6
|
|
|
|
#ifndef EI_NOTINT7
|
|
ISR(INT7_vect) {/*{{{*/
|
|
#ifndef NEEDFORSPEED
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
arduinoInterruptedPin=ARDUINO_PIN_E7; arduinoPinState=PINE & _BV(7);
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
(*functionPointerArrayEXTERNAL[7])();
|
|
#else
|
|
#ifdef INTERRUPT_FLAG_PIN76
|
|
INTERRUPT_FLAG_PIN76++;
|
|
#endif
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTINT7
|
|
#endif // defined ARDUINO_MEGA
|
|
|
|
#if defined ARDUINO_LEONARDO
|
|
#ifndef EI_NOTINT6
|
|
ISR(INT6_vect) {/*{{{*/
|
|
#ifndef NEEDFORSPEED
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
arduinoInterruptedPin=ARDUINO_PIN_E6; arduinoPinState=PINE & _BV(6);
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
(*functionPointerArrayEXTERNAL[4])();
|
|
#else
|
|
#ifdef INTERRUPT_FLAG_PIN7
|
|
INTERRUPT_FLAG_PIN7++;
|
|
#endif
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTINT6
|
|
#endif // defined ARDUINO_LEONARDO
|
|
#endif // EI_NOTEXTERNAL
|
|
// *************************************************************************************
|
|
// *************************************************************************************
|
|
|
|
// *************************************************************************************
|
|
// Pin Change Interrupts
|
|
// *************************************************************************************
|
|
#ifndef EI_NOTPORTA
|
|
ISR(PORTA_VECT) {/*{{{*/
|
|
uint8_t current;
|
|
uint8_t interruptMask;
|
|
uint8_t changedPins;
|
|
uint8_t tmp;
|
|
|
|
current=PINA;
|
|
// If we trust the compiler to do this, it will use an extra register...
|
|
// changedPins=(portSnapshotA ^ current) &
|
|
// ((risingPinsPORTA & current) | (fallingPinsPORTA & ~current));
|
|
// ...so we do it ourselves:
|
|
changedPins = portSnapshotA ^ current;
|
|
tmp = risingPinsPORTA & current;
|
|
interruptMask = fallingPinsPORTA & ~current;
|
|
interruptMask = interruptMask | tmp;
|
|
interruptMask = changedPins & interruptMask;
|
|
interruptMask = PCMSK0 & interruptMask;
|
|
|
|
|
|
portSnapshotA = current;
|
|
#ifdef NEEDFORSPEED
|
|
#include "utility/ei_porta_speed.h"
|
|
#else
|
|
if (interruptMask == 0) goto exitPORTAISR; // get out quickly if not interested.
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
if (interruptMask & _BV(0)) { arduinoInterruptedPin=ARDUINO_PIN_A0; arduinoPinState=current & _BV(0); portAFunctions.pinZero(); }
|
|
if (interruptMask & _BV(1)) { arduinoInterruptedPin=ARDUINO_PIN_A1; arduinoPinState=current & _BV(1); portAFunctions.pinOne(); }
|
|
if (interruptMask & _BV(2)) { arduinoInterruptedPin=ARDUINO_PIN_A2; arduinoPinState=current & _BV(2); portAFunctions.pinTwo(); }
|
|
if (interruptMask & _BV(3)) { arduinoInterruptedPin=ARDUINO_PIN_A3; arduinoPinState=current & _BV(3); portAFunctions.pinThree(); }
|
|
if (interruptMask & _BV(4)) { arduinoInterruptedPin=ARDUINO_PIN_A4; arduinoPinState=current & _BV(4); portAFunctions.pinFour(); }
|
|
if (interruptMask & _BV(5)) { arduinoInterruptedPin=ARDUINO_PIN_A5; arduinoPinState=current & _BV(5); portAFunctions.pinFive(); }
|
|
if (interruptMask & _BV(6)) { arduinoInterruptedPin=ARDUINO_PIN_A6; arduinoPinState=current & _BV(6); portAFunctions.pinSix(); }
|
|
if (interruptMask & _BV(7)) { arduinoInterruptedPin=ARDUINO_PIN_A7; arduinoPinState=current & _BV(7); portAFunctions.pinSeven(); }
|
|
#else
|
|
if (interruptMask & _BV(0)) portAFunctions.pinZero();
|
|
if (interruptMask & _BV(1)) portAFunctions.pinOne();
|
|
if (interruptMask & _BV(2)) portAFunctions.pinTwo();
|
|
if (interruptMask & _BV(3)) portAFunctions.pinThree();
|
|
if (interruptMask & _BV(4)) portAFunctions.pinFour();
|
|
if (interruptMask & _BV(5)) portAFunctions.pinFive();
|
|
if (interruptMask & _BV(6)) portAFunctions.pinSix();
|
|
if (interruptMask & _BV(7)) portAFunctions.pinSeven();
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
exitPORTAISR: return;
|
|
#endif // NEEDFORSPEED
|
|
// FOR MEASUREMENT ONLY
|
|
// exitPORTBISR: PORTC &= ~(1 << PC5); // SIGNAL THAT WE ARE LEAVING THE INTERRUPT
|
|
}/*}}}*/
|
|
#endif // EI_NOTPORTA
|
|
|
|
#ifndef EI_NOTPORTB
|
|
ISR(PORTB_VECT) {/*{{{*/
|
|
uint8_t current;
|
|
uint8_t interruptMask;
|
|
uint8_t changedPins;
|
|
uint8_t tmp;
|
|
|
|
current=PINB;
|
|
// If we trust the compiler to do this, it will use an extra register...
|
|
// changedPins=(portSnapshotB ^ current) &
|
|
// ((risingPinsPORTB & current) | (fallingPinsPORTB & ~current));
|
|
// ...so we do it ourselves:
|
|
changedPins = portSnapshotB ^ current;
|
|
tmp = risingPinsPORTB & current;
|
|
interruptMask = fallingPinsPORTB & ~current;
|
|
interruptMask = interruptMask | tmp;
|
|
interruptMask = changedPins & interruptMask;
|
|
#if (defined MIGHTY1284) || (defined EI_ATTINY24)
|
|
interruptMask = PCMSK1 & interruptMask;
|
|
#else
|
|
#ifdef EI_ATTINY25
|
|
interruptMask = PCMSK & interruptMask;
|
|
#else
|
|
interruptMask = PCMSK0 & interruptMask;
|
|
#endif
|
|
#endif
|
|
|
|
portSnapshotB = current;
|
|
#ifdef NEEDFORSPEED
|
|
#include "utility/ei_portb_speed.h"
|
|
#else
|
|
if (interruptMask == 0) goto exitPORTBISR; // get out quickly if not interested.
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
if (interruptMask & _BV(0)) { arduinoInterruptedPin=ARDUINO_PIN_B0; arduinoPinState=current & _BV(0); portBFunctions.pinZero(); }
|
|
if (interruptMask & _BV(1)) { arduinoInterruptedPin=ARDUINO_PIN_B1; arduinoPinState=current & _BV(1); portBFunctions.pinOne(); }
|
|
if (interruptMask & _BV(2)) { arduinoInterruptedPin=ARDUINO_PIN_B2; arduinoPinState=current & _BV(2); portBFunctions.pinTwo(); }
|
|
if (interruptMask & _BV(3)) { arduinoInterruptedPin=ARDUINO_PIN_B3; arduinoPinState=current & _BV(3); portBFunctions.pinThree(); }
|
|
#if ! (defined EI_ATTINY24)
|
|
if (interruptMask & _BV(4)) { arduinoInterruptedPin=ARDUINO_PIN_B4; arduinoPinState=current & _BV(4); portBFunctions.pinFour(); }
|
|
if (interruptMask & _BV(5)) { arduinoInterruptedPin=ARDUINO_PIN_B5; arduinoPinState=current & _BV(5); portBFunctions.pinFive(); }
|
|
#endif
|
|
#if ! (defined ARDUINO_328) && ! (defined EI_ATTINY24) && ! (defined EI_ATTINY25)
|
|
if (interruptMask & _BV(6)) { arduinoInterruptedPin=ARDUINO_PIN_B6; arduinoPinState=current & _BV(6); portBFunctions.pinSix(); }
|
|
if (interruptMask & _BV(7)) { arduinoInterruptedPin=ARDUINO_PIN_B7; arduinoPinState=current & _BV(7); portBFunctions.pinSeven(); }
|
|
#endif
|
|
#else // EI_ARDUINO_INTERRUPTED_PIN
|
|
if (interruptMask & _BV(0)) portBFunctions.pinZero();
|
|
if (interruptMask & _BV(1)) portBFunctions.pinOne();
|
|
if (interruptMask & _BV(2)) portBFunctions.pinTwo();
|
|
if (interruptMask & _BV(3)) portBFunctions.pinThree();
|
|
#if ! (defined EI_ATTINY24)
|
|
if (interruptMask & _BV(4)) portBFunctions.pinFour();
|
|
if (interruptMask & _BV(5)) portBFunctions.pinFive();
|
|
#endif
|
|
#if ! (defined ARDUINO_328) && ! (defined EI_ATTINY24) && ! (defined EI_ATTINY25)
|
|
if (interruptMask & _BV(6)) portBFunctions.pinSix();
|
|
if (interruptMask & _BV(7)) portBFunctions.pinSeven();
|
|
#endif
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
exitPORTBISR: return;
|
|
// FOR MEASUREMENT ONLY
|
|
// exitPORTBISR: PORTC &= ~(1 << PC5); // SIGNAL THAT WE ARE LEAVING THE INTERRUPT
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTPORTB
|
|
|
|
#ifndef EI_NOTPORTC
|
|
ISR(PORTC_VECT) {/*{{{*/
|
|
uint8_t current;
|
|
uint8_t interruptMask;
|
|
uint8_t changedPins;
|
|
uint8_t tmp;
|
|
|
|
current=PINC;
|
|
// If we trust the compiler to do this, it will use an extra register...
|
|
// changedPins=(portSnapshotB ^ current) &
|
|
// ((risingPinsPORTB & current) | (fallingPinsPORTB & ~current));
|
|
// ...so we do it ourselves:
|
|
changedPins = portSnapshotC ^ current;
|
|
tmp = risingPinsPORTC & current;
|
|
interruptMask = fallingPinsPORTC & ~current;
|
|
interruptMask = interruptMask | tmp;
|
|
interruptMask = changedPins & interruptMask;
|
|
#if (defined MIGHTY1284)
|
|
interruptMask = PCMSK2 & interruptMask;
|
|
#else
|
|
interruptMask = PCMSK1 & interruptMask;
|
|
#endif
|
|
|
|
portSnapshotC = current;
|
|
#ifdef NEEDFORSPEED
|
|
#include "utility/ei_portc_speed.h"
|
|
#else
|
|
if (interruptMask == 0) goto exitPORTCISR; // get out quickly if not interested.
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
if (interruptMask & _BV(0)) { arduinoInterruptedPin=ARDUINO_PIN_C0; arduinoPinState=current & _BV(0); portCFunctions.pinZero(); }
|
|
if (interruptMask & _BV(1)) { arduinoInterruptedPin=ARDUINO_PIN_C1; arduinoPinState=current & _BV(1); portCFunctions.pinOne(); }
|
|
if (interruptMask & _BV(2)) { arduinoInterruptedPin=ARDUINO_PIN_C2; arduinoPinState=current & _BV(2); portCFunctions.pinTwo(); }
|
|
if (interruptMask & _BV(3)) { arduinoInterruptedPin=ARDUINO_PIN_C3; arduinoPinState=current & _BV(3); portCFunctions.pinThree(); }
|
|
if (interruptMask & _BV(4)) { arduinoInterruptedPin=ARDUINO_PIN_C4; arduinoPinState=current & _BV(4); portCFunctions.pinFour(); }
|
|
if (interruptMask & _BV(5)) { arduinoInterruptedPin=ARDUINO_PIN_C5; arduinoPinState=current & _BV(5); portCFunctions.pinFive(); }
|
|
#ifdef MIGHTY1284
|
|
if (interruptMask & _BV(6)) { arduinoInterruptedPin=ARDUINO_PIN_C6; arduinoPinState=current & _BV(6); portCFunctions.pinSix(); }
|
|
if (interruptMask & _BV(7)) { arduinoInterruptedPin=ARDUINO_PIN_C7; arduinoPinState=current & _BV(7); portCFunctions.pinSeven(); }
|
|
#endif
|
|
#else
|
|
if (interruptMask & _BV(0)) portCFunctions.pinZero();
|
|
if (interruptMask & _BV(1)) portCFunctions.pinOne();
|
|
if (interruptMask & _BV(2)) portCFunctions.pinTwo();
|
|
if (interruptMask & _BV(3)) portCFunctions.pinThree();
|
|
if (interruptMask & _BV(4)) portCFunctions.pinFour();
|
|
if (interruptMask & _BV(5)) portCFunctions.pinFive();
|
|
#ifdef MIGHTY1284
|
|
if (interruptMask & _BV(6)) portCFunctions.pinSix();
|
|
if (interruptMask & _BV(7)) portCFunctions.pinSeven();
|
|
#endif
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
exitPORTCISR: return;
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTPORTC
|
|
|
|
#ifndef EI_NOTPORTD
|
|
ISR(PORTD_VECT) {/*{{{*/
|
|
uint8_t current;
|
|
uint8_t interruptMask;
|
|
uint8_t changedPins;
|
|
uint8_t tmp;
|
|
|
|
current=PIND;
|
|
// If we trust the compiler to do this, it will use an extra register...
|
|
// changedPins=(portSnapshotB ^ current) &
|
|
// ((risingPinsPORTB & current) | (fallingPinsPORTB & ~current));
|
|
// ...so we do it ourselves:
|
|
changedPins = portSnapshotD ^ current;
|
|
tmp = risingPinsPORTD & current;
|
|
interruptMask = fallingPinsPORTD & ~current;
|
|
interruptMask = interruptMask | tmp;
|
|
interruptMask = changedPins & interruptMask;
|
|
#if (defined MIGHTY1284)
|
|
interruptMask = PCMSK3 & interruptMask;
|
|
#else
|
|
interruptMask = PCMSK2 & interruptMask;
|
|
#endif
|
|
|
|
portSnapshotD = current;
|
|
#ifdef NEEDFORSPEED
|
|
#include "utility/ei_portd_speed.h"
|
|
#else
|
|
if (interruptMask == 0) goto exitPORTDISR; // get out quickly if not interested.
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
if (interruptMask & _BV(0)) { arduinoInterruptedPin=ARDUINO_PIN_D0; arduinoPinState=current & _BV(0); portDFunctions.pinZero(); }
|
|
if (interruptMask & _BV(1)) { arduinoInterruptedPin=ARDUINO_PIN_D1; arduinoPinState=current & _BV(1); portDFunctions.pinOne(); }
|
|
if (interruptMask & _BV(2)) { arduinoInterruptedPin=ARDUINO_PIN_D2; arduinoPinState=current & _BV(2); portDFunctions.pinTwo(); }
|
|
if (interruptMask & _BV(3)) { arduinoInterruptedPin=ARDUINO_PIN_D3; arduinoPinState=current & _BV(3); portDFunctions.pinThree(); }
|
|
if (interruptMask & _BV(4)) { arduinoInterruptedPin=ARDUINO_PIN_D4; arduinoPinState=current & _BV(4); portDFunctions.pinFour(); }
|
|
if (interruptMask & _BV(5)) { arduinoInterruptedPin=ARDUINO_PIN_D5; arduinoPinState=current & _BV(5); portDFunctions.pinFive(); }
|
|
if (interruptMask & _BV(6)) { arduinoInterruptedPin=ARDUINO_PIN_D6; arduinoPinState=current & _BV(6); portDFunctions.pinSix(); }
|
|
if (interruptMask & _BV(7)) { arduinoInterruptedPin=ARDUINO_PIN_D7; arduinoPinState=current & _BV(7); portDFunctions.pinSeven(); }
|
|
#else
|
|
if (interruptMask & _BV(0)) portDFunctions.pinZero();
|
|
if (interruptMask & _BV(1)) portDFunctions.pinOne();
|
|
if (interruptMask & _BV(2)) portDFunctions.pinTwo();
|
|
if (interruptMask & _BV(3)) portDFunctions.pinThree();
|
|
if (interruptMask & _BV(4)) portDFunctions.pinFour();
|
|
if (interruptMask & _BV(5)) portDFunctions.pinFive();
|
|
if (interruptMask & _BV(6)) portDFunctions.pinSix();
|
|
if (interruptMask & _BV(7)) portDFunctions.pinSeven();
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
exitPORTDISR: return;
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTPORTD
|
|
|
|
#ifndef EI_NOTPORTJ
|
|
ISR(PORTJ_VECT) {/*{{{*/
|
|
uint8_t current;
|
|
uint8_t interruptMask;
|
|
uint8_t changedPins;
|
|
uint8_t tmp;
|
|
|
|
current=PINJ;
|
|
// If we trust the compiler to do this, it will use an extra register...
|
|
// changedPins=(portSnapshotB ^ current) &
|
|
// ((risingPinsPORTB & current) | (fallingPinsPORTB & ~current));
|
|
// ...so we do it ourselves:
|
|
changedPins = portSnapshotJ ^ current;
|
|
tmp = risingPinsPORTJ & current;
|
|
interruptMask = fallingPinsPORTJ & ~current;
|
|
interruptMask = interruptMask | tmp;
|
|
interruptMask = changedPins & interruptMask;
|
|
interruptMask = portJPCMSK & interruptMask; // because PCMSK1 is shifted wrt. PortJ.
|
|
|
|
portSnapshotJ = current;
|
|
#ifdef NEEDFORSPEED
|
|
#include "utility/ei_portj_speed.h"
|
|
#else
|
|
if (interruptMask == 0) goto exitPORTJISR; // get out quickly if not interested.
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
if (interruptMask & _BV(0)) { arduinoInterruptedPin=ARDUINO_PIN_J0; arduinoPinState=current & _BV(0); portJFunctions.pinZero(); }
|
|
if (interruptMask & _BV(1)) { arduinoInterruptedPin=ARDUINO_PIN_J1; arduinoPinState=current & _BV(1); portJFunctions.pinOne(); }
|
|
if (interruptMask & _BV(2)) { arduinoInterruptedPin=ARDUINO_PIN_J2; arduinoPinState=current & _BV(2); portJFunctions.pinTwo(); }
|
|
if (interruptMask & _BV(3)) { arduinoInterruptedPin=ARDUINO_PIN_J3; arduinoPinState=current & _BV(3); portJFunctions.pinThree(); }
|
|
if (interruptMask & _BV(4)) { arduinoInterruptedPin=ARDUINO_PIN_J4; arduinoPinState=current & _BV(4); portJFunctions.pinFour(); }
|
|
if (interruptMask & _BV(5)) { arduinoInterruptedPin=ARDUINO_PIN_J5; arduinoPinState=current & _BV(5); portJFunctions.pinFive(); }
|
|
if (interruptMask & _BV(6)) { arduinoInterruptedPin=ARDUINO_PIN_J6; arduinoPinState=current & _BV(6); portJFunctions.pinSix(); }
|
|
#else
|
|
if (interruptMask & _BV(0)) portJFunctions.pinZero();
|
|
if (interruptMask & _BV(1)) portJFunctions.pinOne();
|
|
if (interruptMask & _BV(2)) portJFunctions.pinTwo();
|
|
if (interruptMask & _BV(3)) portJFunctions.pinThree();
|
|
if (interruptMask & _BV(4)) portJFunctions.pinFour();
|
|
if (interruptMask & _BV(5)) portJFunctions.pinFive();
|
|
if (interruptMask & _BV(6)) portJFunctions.pinSix();
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
exitPORTJISR: return;
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTPORTJ
|
|
|
|
#ifndef EI_NOTPORTK
|
|
ISR(PORTK_VECT) {/*{{{*/
|
|
uint8_t current;
|
|
uint8_t interruptMask;
|
|
uint8_t changedPins;
|
|
uint8_t tmp;
|
|
|
|
current=PINK;
|
|
// If we trust the compiler to do this, it will use an extra register...
|
|
// changedPins=(portSnapshotB ^ current) &
|
|
// ((risingPinsPORTB & current) | (fallingPinsPORTB & ~current));
|
|
// ...so we do it ourselves:
|
|
changedPins = portSnapshotK ^ current;
|
|
tmp = risingPinsPORTK & current;
|
|
interruptMask = fallingPinsPORTK & ~current;
|
|
interruptMask = interruptMask | tmp;
|
|
interruptMask = changedPins & interruptMask;
|
|
interruptMask = PCMSK2 & interruptMask;
|
|
|
|
portSnapshotK = current;
|
|
#ifdef NEEDFORSPEED
|
|
#include "utility/ei_portk_speed.h"
|
|
#else
|
|
if (interruptMask == 0) goto exitPORTKISR; // get out quickly if not interested.
|
|
#ifdef EI_ARDUINO_INTERRUPTED_PIN
|
|
if (interruptMask & _BV(0)) { arduinoInterruptedPin=ARDUINO_PIN_K0; arduinoPinState=current & _BV(0); portKFunctions.pinZero(); }
|
|
if (interruptMask & _BV(1)) { arduinoInterruptedPin=ARDUINO_PIN_K1; arduinoPinState=current & _BV(1); portKFunctions.pinOne(); }
|
|
if (interruptMask & _BV(2)) { arduinoInterruptedPin=ARDUINO_PIN_K2; arduinoPinState=current & _BV(2); portKFunctions.pinTwo(); }
|
|
if (interruptMask & _BV(3)) { arduinoInterruptedPin=ARDUINO_PIN_K3; arduinoPinState=current & _BV(3); portKFunctions.pinThree(); }
|
|
if (interruptMask & _BV(4)) { arduinoInterruptedPin=ARDUINO_PIN_K4; arduinoPinState=current & _BV(4); portKFunctions.pinFour(); }
|
|
if (interruptMask & _BV(5)) { arduinoInterruptedPin=ARDUINO_PIN_K5; arduinoPinState=current & _BV(5); portKFunctions.pinFive(); }
|
|
if (interruptMask & _BV(6)) { arduinoInterruptedPin=ARDUINO_PIN_K6; arduinoPinState=current & _BV(6); portKFunctions.pinSix(); }
|
|
if (interruptMask & _BV(7)) { arduinoInterruptedPin=ARDUINO_PIN_K7; arduinoPinState=current & _BV(7); portKFunctions.pinSeven(); }
|
|
#else
|
|
if (interruptMask & _BV(0)) portKFunctions.pinZero();
|
|
if (interruptMask & _BV(1)) portKFunctions.pinOne();
|
|
if (interruptMask & _BV(2)) portKFunctions.pinTwo();
|
|
if (interruptMask & _BV(3)) portKFunctions.pinThree();
|
|
if (interruptMask & _BV(4)) portKFunctions.pinFour();
|
|
if (interruptMask & _BV(5)) portKFunctions.pinFive();
|
|
if (interruptMask & _BV(6)) portKFunctions.pinSix();
|
|
if (interruptMask & _BV(7)) portKFunctions.pinSeven();
|
|
#endif // EI_ARDUINO_INTERRUPTED_PIN
|
|
exitPORTKISR: return;
|
|
#endif // NEEDFORSPEED
|
|
}/*}}}*/
|
|
#endif // EI_NOTPORTK
|
|
|
|
// *************************************************************************************
|
|
// *************************************************************************************
|
|
|
|
#endif // #ifndef LIBCALL_ENABLEINTERRUPT *********************************************************
|
|
#endif // #if defined __SAM3U4E__ || defined __SAM3X8E__ || defined __SAM3X8H__
|
|
#endif // #ifndef EnableInterrupt_h ***************************************************************
|